JDK-6293787 : Unexpected memory growth while using Inflater/Deflater classes
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 1.4.2_04,1.4.2_08
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: solaris_8,windows_2003
  • CPU: x86,sparc
  • Submitted: 2005-07-02
  • Updated: 2013-03-18
  • Resolved: 2013-03-18
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Siebel calls for Inflater and Deflater object in the following way
       * insider a method a new Deflater object is created and assigned to a local reference.
       * Deflation takes place immediately, end() not called
       * After deflation local reference goes out of scope when method exists, object is available for GC.
       * This method is called many times (each time a new Deflater is constructed and discarded).
      * Each time, buffer size is in the order of 1K (not exact).
       A possible, but unlikely reason ("Unlikely reason") could be: GC bug, when the count of Delater/Inflater objects available for GC but not yet GCed is continuously increasing.
     Alternatively the native implementation has memory leaks, as it does not stand to reason that continuous memory growth is caused by "Unlikely reason", but rather as a result of native memory not properly released in some cases.

I have suggested that a explicit end() be included in code but  Siebel says that memory growth continues with end() call too.

###@###.### 2005-07-02 02:27:13 GMT
User sends a new test case to replicate the problem. 
The test case is enclosed.
(moved comments to Comments section.)

EVALUATION Several improvements to finalization are planned for dolphin; once implelented, they should address this problem. Will add the RFE numbers here once they have been filed.

WORK AROUND The preferred workaround is to use the end() and reset() methods and reuse Inflater/Deflater objects to avoid the need for mass finalization. Alternatively, use the end() method and call System.runFinalization() periodically. Note that calling end() is recommended in both cases. Finalizable objects are discovered by GC, which occurs when there is pressure on the java heap. The c-heap memory allocated by Inflater/Deflater will not trigger GCs, so the c-heap may fill up before GC detects and enqueues unreachable finalizable objects.

EVALUATION I ran the latest version of DeflateTest4.java (attached) with the arguments -e -i 2000 bigfile.txt 10 12 512000 The '-e' argument causes 'end()' to be called; '-i 2000' causes each thread to call System.runFinalization() every 2 seconds. The memory usage reached steady state and has stayed constant for 8+ hours. So there is no memory leak; the test case relies on prompt finalization.

EVALUATION This looks like another instance of the finalizer thread not being able to keep up with the application. The java.util.zip.{Deflater,Inflater} classes have finalize() methods which release c-heap buffers allocated by native code. The same buffers can be freed before the {Deflater,Inflater} obj is finalized by calling end(). The attached test case DeflateTest4.java accepts command-line arguments to control whether end() is called for each Inflator and Deflator after it is no longer needed. The test was run with the arguments 'bigfile.txt 10 12 512000' where bigfile.txt is a 4MB text file. When the end() method *is not* called, the program quickly fills the c-heap to 3+GB and gets OutOfMemoryErrors. When the end() method *is* called, the c-heap stays relatively small, but the java heap eventually fills up with finalizable instances of Inflater/Deflater. Here is the output from -XX:+PrintClassHistogram: num #instances #bytes class name -------------------------------------- 1: 325044 342853728 [B 2: 651501 20848032 java.lang.ref.Finalizer 3: 326816 15687168 java.util.zip.Deflater 4: 324678 12987120 java.util.zip.Inflater 5: 4154 2320264 [I 6: 4424 395256 <constMethodKlass> 7: 4424 391680 <methodKlass> 8: 6504 239408 <symbolKlass> 9: 290 159152 <constantPoolKlass> 10: 290 114000 <instanceKlassKlass> 11: 270 113376 <constantPoolCacheKlass> I modified DeflateTest4.java to allow command-line control over the frequency with which System.runFinalization() is called. A brief run indicated that memory usage plateaus if runFinalization() is called frequently. Will run overnight.