2

I need to read the Manifest file from a jar file at runtime.

Code:

JarFile someJar = new JarFile(jarFile);
manifest = someJar.getManifest();

However, sometimes above code throw OutOfMemoryError exception:

java.lang.OutOfMemoryError
    at java.util.zip.Inflater.init(Native Method)
    at java.util.zip.Inflater.<init>(Inflater.java:83)
    at java.util.zip.ZipFile.getInflater(ZipFile.java:278)
    at java.util.zip.ZipFile.getInputStream(ZipFile.java:224)
    at java.util.zip.ZipFile.getInputStream(ZipFile.java:192)
    at java.util.jar.JarFile.getBytes(JarFile.java:361)

Can sometime tell me how avoid this exception (maybe another way to get the manifest at runtime)?

btw, I don't have the permission to change the java heap size.

Terminal User
  • 873
  • 3
  • 13
  • 21

3 Answers3

0

Is it not a corrupt jar file that is confusing the Inflater into thinking that it needs to allocate a huge amount of memory?

If it is, you will probably find that you can actually catch the OutOfMemoryError. (You generally can't or shouldn't catch these, but in the specific case of an attempt to allocate a huge amount of memory that isn't available, it is generally safe to do so in practice.)

Neil Coffey
  • 21,615
  • 7
  • 62
  • 83
0

This may not have anything to do with the ZIP file that you're running against.

Looking at the JDK 1.7 code, the Inflater constructor ends up calling a native method named init, providing it with a boolean argument. There's no sign there to any reference to the ZIP file.

It seems like either there's a bug in the JRE you're using, or your system is extremely limited in heap memory (the native ZIP library, containing most of the ZIP functionality, is very small).

Does your JRE issue a heap dump at the time of the OutOfMemoryError? if so, you might want to look there.

Isaac
  • 16,458
  • 5
  • 57
  • 81
0

This seems is a known issue about java.util.zip.Inflater.

Inflater will allocate out of heap memory during init, if you not call end() after routing, the memory will exists until GC call finalize function. it the heap was huge, finalize() will not called before using up all memory.

please refer to this question: excessive memory use by java ,
or this JDK bug report : http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4797189 .

I am verify it by bellow code, until to JDK8, it still exists.

public static void main( String args[] ) throws InterruptedException {
    while ( true ) {
        //final Deflater deflater = new Deflater( 9, true );
        final Inflater inflater = new Inflater( true );
        // ....
        // if not call end() after using inflater, it will OOM
        // inflater.end();
        Thread.sleep(10);
    }
}

The solution is so simple, just call end()* after finished using inflater.

Community
  • 1
  • 1
Santal Li
  • 126
  • 1
  • 7