Pack200 and Compression |
This chapter includes the following topics:
To increase server and network availability and band-width, two new compression formats are available to Java deployment of applications and applets: gzip and Pack200.
With both techniques the compressed JAR files are transmitted over the network and the receiving application decompresses and restores them.
HTTP 1.1 (RFC 2616) protocol discusses HTTP compression. HTTP Compression allows applications JAR files to be deployed as compressed JAR files. The supported compression techniques are gzip,compress,deflate.
As of SDK/JRE version 5.0, HTTP compression is implemented in Java Web Start
and Java Plug-in in compliance with RFC 2616. The supported techniques are
gzip and pack200-gzip.
The requesting application sends an
HTTP request to the server. An HTTP request has multiple fields. The
Accept-Encoding (AE) field is set to pack200-gzip
or
gzip
, indicating to the server that the application can handle
pack200-gzip
or gzip
format.
The server implementation will search for the requested JAR file with
.pack.gz
or .gz
file extension and respond back with
the located file. The server will set the response header Content-Encoding (CE)
field to pack200-gzip
, gzip
, or NULL depending on the
type of file that is being sent, and optionally may set the Content-Type (CT) to
application/Java-archive. Therefore, by inspecting the CE field, the
requesting application can apply the corresponding transformation to restore the
original JAR file.
The above can be achieved using a simple servlet or server module with any HTTP 1.1 compliant web-servers.
Compressing files on the fly will degrade server performance, especially with Pack200, and therefore not recommended.
Sample Tomcat Servlet:
/** * A simple HTTP Compression Servlet */ import java.util.*; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.zip.*; import java.net.*; /** * The servlet class. */ public class ContentType extends HttpServlet { private static final String JNLP_MIME_TYPE = "application/x-java-jnlp-file"; private static final String JAR_MIME_TYPE = "application/x-java-archive"; private static final String PACK200_MIME_TYPE = "application/x-java-pack200"; // HTTP Compression RFC 2616 : Standard headers public static final String ACCEPT_ENCODING = "accept-encoding"; public static final String CONTENT_TYPE = "content-type"; public static final String CONTENT_ENCODING = "content-encoding"; // HTTP Compression RFC 2616 : Standard header for HTTP/Pack200 Compression public static final String GZIP_ENCODING = "gzip"; public static final String PACK200_GZIP_ENCODING = "pack200-gzip"; private void sendHtml(HttpServletResponse response, String s) throws IOException { PrintWriter out = response.getWriter(); out.println(""); out.println(""); out.println("<title>ContentType</title>"); out.println(""); out.println(""); out.println(s); out.println(""); out.println(""); } /* * Copy the inputStream to output , */ private void sendOut(InputStream in, OutputStream ostream) throws IOException { byte buf[] = new byte[8192]; int n = in.read(buf); while (n > 0 ) { ostream.write(buf,0,n); n = in.read(buf); } ostream.close(); in.close(); } boolean doFile(String name, HttpServletResponse response) { File f = new File(name); if (f.exists()) { getServletContext().log("Found file " + name); response.setContentLength(Integer.parseInt( Long.toString(f.length()))); response.setDateHeader("Last-Modified",f.lastModified()); return true; } getServletContext().log("File not found " + name); return false; } /** Called when someone accesses the servlet. */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String encoding = request.getHeader(ACCEPT_ENCODING); String pathInfo = request.getPathInfo(); String pathInfoEx = request.getPathTranslated(); String contentType = request.getContentType(); StringBuffer requestURL = request.getRequestURL(); String requestName = pathInfo; ServletContext sc = getServletContext(); sc.log("----------------------------"); sc.log("pathInfo="+pathInfo); sc.log("pathInfoEx="+pathInfoEx); sc.log("Accept-Encoding="+encoding); sc.log("Content-Type="+contentType); sc.log("requestURL="+requestURL); if (pathInfoEx == null) { response.sendError(response.SC_NOT_FOUND); return; } String outFile = pathInfo; boolean found = false; String contentEncoding = null; // Pack200 Compression if (encoding != null && contentType != null && contentType.compareTo(JAR_MIME_TYPE) == 0 && encoding.toLowerCase().indexOf(PACK200_GZIP_ENCODING) > -1){ contentEncoding = PACK200_GZIP_ENCODING; if (doFile(pathInfoEx.concat(".pack.gz"),response)) { outFile = pathInfo.concat(".pack.gz") ; found = true; } else { // Pack/Compress and transmit, not very efficient. found = false; } } // HTTP Compression if (found == false && encoding != null && contentType != null && contentType.compareTo(JAR_MIME_TYPE) == 0 && encoding.toLowerCase().indexOf("gzip") > -1) { contentEncoding = GZIP_ENCODING; if (doFile(pathInfoEx.concat(".gz"),response)) { outFile = pathInfo.concat(".gz"); found = true; } } // No Compression if (found == false) { // just send the file contentEncoding = null; sc.log(CONTENT_ENCODING + "=" + "null"); doFile(pathInfoEx,response); outFile = pathInfo; } response.setHeader(CONTENT_ENCODING, contentEncoding); sc.log(CONTENT_ENCODING + "=" + contentEncoding + " : outFile="+outFile); if (sc.getMimeType(pathInfo) != null) { response.setContentType(sc.getMimeType(pathInfo)); } InputStream in = sc.getResourceAsStream(outFile); OutputStream out = response.getOutputStream(); if (in != null) { try { sendOut(in,out); } catch (IOException ioe) { if (ioe.getMessage().compareTo("Broken pipe") == 0) { sc.log("Broken Pipe while writing"); return; } else throw ioe; } } else response.sendError(response.SC_NOT_FOUND); } }
Pack200 compresses large files very efficiently,
depending on the density and size of the class files in the JAR file. One can
expect compression to 1/9 the size of the JAR file, if it contains only class
files and is in the order of several MB.
Using the same jar in the previous
example:
Notepad.jar 46.25
kb
Notepad.jar.pack.gz 22.58 kb
In this case the same jar can be reduced by
50%.
Please note: when signing large jars, step 5 may fail with a Security Error a likely cause is bug 5078608. Please use one of the workarounds detailed in the release notes.
Pack200 works most efficiently on Java class files. It uses several techniques to efficiently reduce the size of JAR files:
Steps to Pack a file
1. Consider the size of the JAR file, the contents of the JAR file, and the bandwidth of your target audience.
All these factors play into choosing a compression technique. The unpack200 is designed to be as efficient as possible and it takes little time to restore the original file. If you have large JAR files (2 MB or more) comprised mostly of class files, Pack200 is the preferred compression technique. If you have large JAR files which are comprised of resource files (JPEG, GIF, data, etc.), then gzip is the preferred compression technique.
2. Pack200 segmenting.
Pack200 loads the entire packed file into memory. However, when target systems are memory and resource constrained, setting the
Pack200.Packer.SEGMENT_LIMIT
to a lower value, will reduce the memory requirements during packing and unpacking. ThePack200.Packer.SEGMENT_LIMIT=-1
will force one segment to be generated, which will be effect in size reduction, but will require a much larger Java heap on the packing and and unpacking system. Note that several of these packed segments may be concatenated to produce a single packed file.3. Signing the JAR files.
Pack200 rearranges the contents of the resultant JAR file. The jarsigner hashes the contents of the class file and stores the hash in an encrypted digest in the manifest. When the unpacker runs on a packed packed, the contents of the classes will be rearranged and thus invalidate the signature. Therefore, the JAR file must be normalized first using pack200 and unpack200, and thereafter signed.
(Here's why this works: Any reordering the packer does of any classfile structures is idempotent, so the second packing does not change the orderings produced by the first packing. Also, the unpacker is guaranteed by the JSR 200 specification to produce a specific bytewise image for any given transmission ordering of archive elements.)
An Example
Suppose you wish to use HelloWorld.jar.
Step 1: Repack the file to normalize the jar, repacking calls the packer and unpacks the file in one step.% pack200 --repack HelloWorld.jar
Step 2: Sign the jar after we normalize using repack.% jarsigner -keystore myKeystore HelloWorld.jar ksrini
Verify the just signed jar to ensure the signing worked.% jarsigner -verify HelloWorld.jar
jar verified.
Ensure the jar still works.% Java -jar HelloWorld.jar
HelloWorld
Step 3: Now we pack the file% pack200 HelloWorld.jar.pack.gz HelloWorld.jar
Step 4: Unpack the file% unpack200 HelloWorld.jar.pack.gz HelloT1.jar
Step 5: Verify the jar% jarsigner -verify HelloT1.jar
jar verified.
// Test the jar ...% Java -jar HelloT1.jar
HelloWorld
After verification, the compressed pack file HelloWorld.jar.pack.gz can be deployed.4. Reduction techniques:
Pack200 by default behaves in a High Fidelity (Hi-Fi) mode, meaning all the original attributes present in the classes as well as the attributes of each individual entry in a JAR file is retained. These typically tend to add to the packed file size, here are some of the
techniques one can use to further reduce the size of the download:
- Modification times: If modification time of the individual entries in a JAR file is not a concern, you can specify the option
Pack200.Packer.MODIFICATION_TIME="LATEST"
. This will allow one modification time to be transmitted in the pack file for each segment. The latest time will be the latest time of any entry within that segment.- Deflation hint: Similar to the above, if the compression state of the individual entries in the archive is not required, set Pack200.Packer.DEFLATION_HINT="false". This will fractionally reduce the download size, as individual compression hints will not be transmitted. However, the jar when recomposed will contain "stored" entries and hence may consume more disk space on the target system.
For example:
pack200 --modification-time=latest --deflate-hint="true" tools-md.jar.pack.gz tools.jar
Note: the above optimizations will yield better results with a JAR file containing thousands of entries.
- Attributes: Several class attributes are not required when deploying JAR files. These attributes can be stripped out of class files, significantly reducing download size. However, care must be taken to ensure that required runtime attributes are maintained.
- Debugging attributes: If debugging information, such as Line Numbers and Source File, is not required (typically in applications stack traces), then these attributes can be discarded by specifying
Pack200.Packer.STRIP_DEBUG=true.
This typically reduces the packed file by about 10%.Example:
pack200 --strip-debug tools-stripped.jar.pack.gz tools.jar
- Other attributes: Advanced users may use some of the other strip-related properties to strip out additional attributes. However, extreme caution should be used when doing so, the resultant JAR file must be tested on all possible Java runtime systems to ensure that the runtime does not depend on the stripped attributes.
5. Handling unknown attributes:
6. Installers:Pack200 deals with standard attributes defined by the Java Virtual Machine Specification, however compilers are free to introduce custom attributes. When such attributes are present, by default, Pack200 passes through the class, emitting a warning message. These "passed-through" class files, may contribute to bloating of packed files. If the unknown attributes are prevalent in the classes of a JAR file, this may lead to a very large bloat of the packed output. In such a cases, consider the following strategies:
Strip the attribute if the attribute is deemed to be redundant at runtime, this can be achieved by setting the property Pack200.Packer.
UNKNOWN_ATTRIBUTE=STRIP or
pack200 --unknown-attribute=strip foo.pack.gz foo.jar
If the attributes are required at runtime, and they do contribute to an inflation, then identify the attribute from the warning message and apply a suitable layout for these, as described in the Pack200 JSR 200 specification., and the Java API reference section for Pack200.Packer.
Its possible that a compiler could define an attribute not implemented in the layout specification of Pack200, and may cause the Packer to malfunction, in such cases an entire class file(s) can be "passed through", as if it were a resource by virtue of its name and can be specified as follows:
pack200 --pass-file="com/acme/foo/bar/baz.class" foo.pack.gz foo.jar
or an entire directory and its contents,pack200 --pass-file="com/acme/foo/bar/" foo.pack.gz foo.jar
You may wish to take advantage of the Pack200 technology in your installation program, whereby a product's jars may need to compressed using Pack200 and decompressed during the installation. If the JRE or SDK is bundled in the installation, you are free to use the unpack200 (Unix) or unpack200.exe(Windows) in the distribution 'bin' directory, this implementation is a pure C++ application requiring no Java runtime to be present for it to run.Windows: Installers may use a better algorithm than the one in GZIP to compress entries in such cases, one will get better compression using the Installer's intrinsic compression, by using the pack200 as follows:
pack200 --no-gzip foo.jar.pack foo.jar
This will prevent the output file from being gzip compressed.
unpack200 is a Windows Console application, ie. it will display a MS-DOS window during the install, to suppress this, you can use a launcher with a WinMain which will suppress this window, as shown below.
Sample Code:
#include "windows.h" #include <stdio.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(pi)); //Test //lpCmdLine = "c:/build/windows-i586/bin/unpack200 -l c:/Temp/log c:/Temp/rt.pack c:/Temp/rt.jar"; int ret = CreateProcess(NULL, /* Exec. name */ lpCmdLine, /* cmd line */ NULL, /* proc. sec. attr. */ NULL, /* thread sec. attr */ TRUE, /* inherit file handle */ CREATE_NO_WINDOW | DETACHED_PROCESS, /* detach the process/suppress console */ NULL, /* env block */ NULL, /* inherit cwd */ &si, /* startup info */ &pi); /* process info */ if ( ret == 0) ExitProcess(255); // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); DWORD exit_val; // Be conservative and return if (GetExitCodeProcess(pi.hProcess, &exit_val) == 0) ExitProcess(255); ExitProcess(exit_val); // Return the error code of the child process return -1; }
It is required that all JAR files, packed and
unpacked, be tested for correctness with your applications test qualifiers.
When using the command line interface pack200
, the output file
will be compressed using gzip
with default values. A user
may create a simple pack file and compress using gzip
with user-specified options or using some other compressor.
For more information see
pack200
andunpack200
in Java Deployment Tools.


On the other hand we have
which is the Hamiltonian. We note that it is the energy expressed in terms
of generalized coordinate and momentum that can be called Hamilton. Using the
Hamilton's equation, it can be easily proved that
Further we note that
|
(189) |
In usual case, and are not an explicit function of time,
thus we have
|
(190) |
Using these results, we have
|
(191) |
Then using Eq. (35) we obtain
|
(192) |
|
(193) |
The first order equation of Eq. (192) is (noting that
,
, and is time independent,
thus
,
, and
are all zeros)
|
(194) |
In writing the above expression, we have used the fact that
here is taken by holding constant
, instead of holding constantnt
. In this case obviously
. If we calculate in the second
case, then we would have
,
since
|
(195) |
in which the terms such as
would
explicitly contain . The second term on the right-hand side of Eq.
() can be further calculated as
Then we can use and
in the above equation,
yielding
|
(197) |
Here I have some important comments. First, we note that
is one of the components of the Euler-Lagrange equation, thus of
course can not be substituted into the original Lagrangian
(if
we do this, we can no longer use the resulting Lagrangian as a correct
Lagrangian to obtain correct Euler-Lagrange equation). In contrast to this, it
is obvious we can use one component of the Euler-Lagrangian equation in
another component equation. Thus we can substitute
into Eq. (196) to get Eq. (197). Second, we also substitute into Eq. (196) in obtaining Eq. (197). This is
trivial since what we do is only to rewrite the final result in a different
form. However this kind of rewriting may be misleading to someone (including
me) because the new form can be viewed as being written in terms of a new
variable , instead of the original variable . Of course, for this
case, no matter which variable the right-hand side of Eq. (197) is
understood to be written in terms of, the results are both correct. But it is
crucial to understand correctly which variables Lagrangian
is
written in terms of, since different choice of variables will give different
forms of perturbed Lagrangian because the perturbed Lagrangian is obtained by
keeping the independent variables constant.
Now I calculate the perturbed Lagrangian. The full Lagrangian is given by Eq.
(1), i.e.,
Then the perturbed and linearized version is (note that only the
electromagnetic field is perturbed, the independent variables are keep
constant)
|
(198) |
Using
in Eq. (198), we obtain
Using and
in the above equation, we obtain
|
(200) |
My question is whether it is valid to substitute one of the Euler-Lagrangian
equation
into the perturbed Lagrangian.**wrong!!**
YouJun Hu
2014-05-19


Image of School Building
List of School Activities
RANGOLI
SOLO SINGING (ENGLISH)
GROUP SONG
ENGLISH RECITATION
EXTEMPORE
ONE-ACT PLAY
CLASSICAL DANCE
HINDI/BENGALI RECITATION
GROUP DANCE - FOLK
Video of School Infrastructure
Image Gallery


|
|
|
❧ ❧ ❧
|
|
|
|
❧ ❧ ❧
|
Pairs well with:
- Category: Title. Why it's delightful
- Category: Title. Why it's delightful
- Category: Title. Why it's delightful
- Category: Title. Why it's delightful
|
Thing of the week:
|
Reader recommends:
|
|
❧ ❧ ❧
|
|
Got a recommendation of your own? Hit reply; I’d love to hear from you.
Subscribe, unsubscribe, or learn more on the website.
|
|
This edition of May I Recommend was written from a cozy apartment still adorned with Christmas lights in Chicago, Illinois.
|
|
|


JAVAJAM COFFEE HOUSE
Want to work at JavaJam? Fill out the form below to start your application.
Copyright © 2006 JavaJam Coffee house


My experience in the Software Engineering program at Iowa State
has been a great one. I have learned a lot both in a classroom sense as well as about myself.
As far as coursework, ISU has certianly prepared me to become an engineeer. Courses such as S E 309,
S E 329, S E 339 taught me how to go about designing a system and program it myself. Some of the complicated
programming courses taught me how to solve difficult engineering problems; courses like COM S 430, CPR E
419, and COM S 311 were great for this.
Some of the difficult coursework certainly caused me to look beyond what I learned in class to solve the problems
presented. There were many different resources that I took advantage of to solve these problems. One of these
was using my peers for advice. My peers all have different experiences than myself, so we could help one another
with problems we were having. Beyond this, the internet was a great resource. All sorts of difficult programmming
concepts have great explanations online that I could rely on if I was stuck.
Beyond the technical aspects, I have learned a lot about group work and working for the community.
Classes that emphasized group work, such as S E 309, taught me about being on a team. Beyond that,
being a part of a team at work, at both of my teaching assistant positions as well as my community advisor
position, taught me a lot about being a cohesive unit with your coworkers. The community advisor position
has also opened my eyes to a lot of ethical issues in the world, and has helped me be more attentive of those.
One of my big takeaways from school is my desire to keep learning. Outside of my coursework, I kept learning.
I spent a lot of time learning about mobile application development, both in the Mobile Development Club and on
my own. I am now serving as the club's Android Officer.
I also learned a lot through my teaching assistant positions. I was forced to learn how to think about problems
in many different ways, as others understand problems in different manners to myself. To best help them, I had to
be able to think from their perspective.
If I were to do my undergraduate work again, I would probably try to get more involved in the Computer Science department
earlier on. I've worked in three different positions for them during my time at Iowa State, but I wish I had been doing it
for longer, especially serving as a teaching assistant. My time as a teaching assistant helped me find my love of teaching
others, and I wish I had been able to do it for longer.


OpenDSA: Open Source Interactive
Data Structures and Algorithms
Instructors' Tools
OpenDSA includes useful tools for instructors in what we call the "Teachers' view".
-
Overview of the teachers' view.
-
Instructors can create assignments...
-
Add and/or remove OpenDSA's exercises to the assignment...
-
And track students progress.
For more details on our project infrastructure, status, and issues, see the OpenDSA Wiki.
The OpenDSA Forum contains discussions by the participants related to the project.
If you are a new developer on the project, see The OpenDSA Developer's Getting Started Guide. Further documentation for the OpenDSA infrastructure is available here.
Publications and Presentations
- V. Karavirta and C.A. Shaffer, JSAV: The JavaScript Algorithm Visualization Library, to appear in Proceedings of the 18th Annual Conference on Innovation and Technology in Computer Science Education (ITiCSE 2013), Canterbury, UK, July 2013.
- S. Hall, E. Fouh, D. Breakiron, M. Elshehaly, and C.A. Shaffer, Evaluating Online Tutorials for Data Structures and Algorithms Courses, Proceedings of the 2013 ASEE Annual Conference & Exposition (.pdf, presentation), Atlanta, GA, June 2013, Paper #5951.
- A.M. Paul, QBank: A Web-Based Dynamic Problem Authoring Tool, Masters Thesis, Virginia Tech, June 2013. Defense presentation
- D.A. Breakiron, Evaluating the Integration of Online, Interactive Tutorials into a Data Structures and Algorithms Course, Masters Thesis, Virginia Tech, May 2013. Defense presentation
- E. Fouh, D. Breakiron, M. Elshehaly, T.S. Hall, V. Karavirta, and C.A. Shaffer, OpenDSA: using an active eTextbook to teach data structures and algorithms, poster abstract appears in Proceedings of the 44th ACM Technical Symposium on Computer Science Education, SIGCSE 2013, Denver, CO, March 2013, 734.
- E. Fouh, M. Sun, and C.A. Shaffer, OpenDSA: A Creative Commons Active-eBook, a poster presented at SIGCSE 2012, Raleigh, NC, March 2012.
- C.A. Shaffer, V. Karavirta, A. Korhonen and T.L. Naps, OpenDSA: Beginning a Community Hypertextbook Project in Proceedings of 11th Koli Calling International Conference on Computing Education Research, November 17-20, 2011, Koli National Park, Finland, 112--117.
- C.A. Shaffer, T.L. Naps, and E. Fouh, Interactive Textbooks for Computer Science Education in Proceedings of the Sixth Program Visualization Workshop, June 30, 2011, Darmstadt, Germany, 97-103.
Contact
For more information, or to get involved, please contact Cliff Shaffer at .


I am the author of the graphic novel TEAM PHOTOGRAPH (Sarabande Books, 2022), and the poetry collections INSTEAD OF DYING (winner of the Colorado Prize for Poetry) CALENDAY (Rescue Press, 2014) and THE ECCENTRICITY IS ZERO (Digraph Press, 2014).
I've received the Iowa Artist Fellowship, the Sustainable Arts Foundation Award, the Colorado Prize for Poetry & the fellowships from the Iowa Writers’ Workshop.
My work has appeared in Poetry, Tin House, Colorado Review, Fence, The Iowa Review and The Rumpus.
I work as a web developer, web designer and editor during the daytime. Also: I’m a mom and make paintings.