JDK-8135322 : ConstantPool::release_C_heap_structures not run in some circumstances
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 8u66
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-09-10
  • Updated: 2017-12-10
  • Resolved: 2016-05-19
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.
JDK 8 JDK 9
8u112Fixed 9 b122Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
JDK 8 is leaking memory in VM_RedefineClasses::merge_cp_and_rewrite when repeating class redefinition:

[0x00002aaaab1c2d5a] ConstantPool::ConstantPool(Array<unsigned char>*)+0x6a
[0x00002aaaab1c307c] ConstantPool::allocate(ClassLoaderData*, int, Thread*)+0x14c
[0x00002aaaab48aa7e] VM_RedefineClasses::merge_cp_and_rewrite(instanceKlassHandle, instanceKlassHandle, Thread*)+0x5e
[0x00002aaaab48b5d3] VM_RedefineClasses::load_new_class_versions(Thread*)+0x4c3
            (malloc=84362KB #719885) 
Comments
For JDK 9 ConstantPool::release_C_heap_structures is not run either. It has no lock to leak, but a call to ConstantPool::unreference_symbols done there will never be called.
30-03-2016

After discussing this with Stefan Karlsson, I'm convinced that it is the above change that fixed the memory leak. Usually, a direct free of a constant pool is not needed if the holding ClassLoaderData is going away, since memory is reclaimed automatically because it's part of the metaspace. However, a lock allocated in the constant pool (introduced by JDK-8014910, removed in JDK 9 by JDK-8026977) is not part of the metaspace, and can therefore be leaked under the circumstances mentioned above (classloader marked as not live).
29-03-2016

The leak fixed in JDK-8026977 might also be unrelated - I can't really tell without further investigation, since the NMT detail tracking was not finished in that build.
11-02-2016

Looks like it was JDK-8026977 that fixed it in JDK 9. It might be a bit problematic to backport, so I'll probably do a JDK 8 specific fix for the leak.
10-02-2016

Doesn't look like its JDK-8061205 that fixed this in JDK 9, still working on finding out which change it was.
10-02-2016

This is because the merge constant pool used by class redefinition is not removed properly, even though it's added to the classloader _deallocate_list. I think this is because ClassLoaderDataGraph::do_unloading removes the related classloader from the graph because it is not live, and then runs the ClassLoaderData destructor without cleaning out the _deallocate_list first. This is fixed in 9, most likely by JDK-8061205. Working on verifying that. Two ways of fixing this, either make sure the _deallocate_list is cleaned in ClassLoaderData::~ClassLoaderData, or backport JDK-8061205. Changing this to hotspot/runtime since that's what JDK-8061205 is set to.
09-02-2016

Moved to core-svc/java.lang.instrument since the test case appears to use JLI/JPLIS... Update: If the leak is due to something in the JVM/TI layer, then this bug should be moved to hotspot/jvmti.
17-09-2015