JDK-6531345 : Memory leak in unpack200
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux_2.6
  • CPU: x86
  • Submitted: 2007-03-06
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
7 b109Fixed
Related Reports
Relates :  
We created heap dump and there is a lot of JNI Global references for com.sun.java.util.jar.pack.NativeUnpack. As result there is a lot of unreleased objects on heap. We have about 1000 jars. Is there any way how to force releasing these references?

SUGGESTED FIX NativeUnpack call the finish() after getUnusedInput().

EVALUATION The problem is in NativeUnpack.java the ordering of finish and reading unused bytes for informational purposes causes the native side to create a defunct Global reference.

PUBLIC COMMENTS Unfortunately Marek has already left Sun/Oracle. Steps to reproduce: 1) wget http://download.netbeans.org/netbeans/6.9/final/zip/netbeans-6.9-201006101454-ml.zip 2) unzip netbeans-6.9-201006101454-ml.zip 3) cd netbeans 3) find . -name *.jar > files.list 4) cat > Main.java << EOF import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Pack200; public class Main { public static void main(String[] args) throws Exception { BufferedReader r = new BufferedReader(new FileReader(new File(args[0]))); String line = null; while ((line = r.readLine()) != null) { line = line.trim(); if (line.length() != 0) { File jar = new File(args[1], line); File jarPack = new File(args[1], line + ".pack"); if (jarPack.exists() && args[2].equals("1")) { System.out.println("Unpacking " + jar); unpack(jarPack, jar); } else if (jar.exists() && args[2].equals("0") && !jarPack.exists()) { System.out.println("Packing " + jar); pack(jar, jarPack); } } } if(args[2].equals("1")) { System.gc(); System.gc(); System.out.println("Make heap dump or click abort the application"); Thread.sleep(120000); } } public static void unpack(final File source, final File target) throws IOException { try { JarOutputStream os = new JarOutputStream(new FileOutputStream(target)); Pack200.newUnpacker().unpack(source, os); os.close(); source.delete(); } catch (IOException e) { System.out.println("Cannot unpack " + source + " due to " + e); } } public static void pack(final File source, final File target) throws IOException { JarFile jarFile = null; FileOutputStream outputStream = null; boolean delete = false; try { jarFile = new JarFile(source); outputStream = new FileOutputStream(target); Pack200.newPacker().pack(jarFile, outputStream); } catch (IOException e) { delete = true; System.out.println("Cannot pack " + source + " due to " + e); } finally { if (jarFile != null) { jarFile.close(); } if (outputStream != null) { outputStream.close(); } if(delete) { target.delete(); } } } } EOF 5) javac Main.java 6) java -Xmx1024m -cp . Main files.list . 0 Attaching the profiler shows used heap size constantly groing. At some point you'll get OutOfMemory exception and packer_heapdump.hprof will be written. That is the demonstration of the memory leak in Pack200's packer (CR 6888127). 7) Run it again a few times until no more files are left to be packed - you'll see no output in this case. I ran it 3 times to get rid of the output each time (except the last one) getting OOM. java -Xmx1024m -cp . Main files.list . 0 8) Run unpacker process: java -Xmx1024m -cp . Main files.list . 1 Attaching the profiler shows used heap size constantly groing. Make the heap dump and see that the number of com.sun.java.util.jar.pack.NativeUnpack entries is the same as the number of jars unpacked.

EVALUATION I cannot seem to reproduce the issue, could the submitter provide me with a way to reproduce this problem, also the heap dump will be helpful.

WORK AROUND invoke/exec unpack200.exe which is a standalone app. which should not have the big overhead of starting another jvm.

WORK AROUND We could eventualy run unpack for every jar as separate process. But it would bring another overhead. *** (#1 of 1): [ UNSAVED ] ###@###.###