JDK-8078602 : Support j.l.i.BoundMethodHandle$Species_* classes unloading
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2015-04-24
  • Updated: 2024-06-25
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.
Other
tbdUnresolved
Related Reports
Blocks :  
Relates :  
Description
BMH$Species_* classes are loaded using bootstrap class loader and hence can't be GCed.

src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java: 
            // load class 
            final byte[] classFile = cw.toByteArray(); 
            InvokerBytecodeGenerator.maybeDump(className, classFile); 
            Class<? extends BoundMethodHandle> bmhClass = 
                //UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class); 
                UNSAFE.defineClass(className, classFile, 0, classFile.length, 
                                   BoundMethodHandle.class.getClassLoader(), null) 
                    .asSubclass(BoundMethodHandle.class); 

Consider moving to VM anonymous classes instead. It means all references to Species_* field accessors in LambdaForms should be through method handles and not symbolic references.    
Comments
> I'm pretty sure these are instantiated. I can confirm. The way it works is that we have an abstract base BoundMethodHandle class, and then ClassSpecializer creates sub classes with different additional fields (all the $Species_ classes). Those sub classes are then instantiated, and used to implement method handles that have arguments bound to them.
25-06-2024

There's also a ConcurrentHashMap cache in ClassSpecializer that stores all the generated SpeciesData which looks like it would have to be changed to use WeakReferences.
25-06-2024

To make the species class weak, we might have to change BoundMethodHandle.SpeciesData::extensions array to hold WeakReference; don't know how big an impact this will have on Leyden. Alternatively, we can change the specializer key type to MethodTypeForm and store the species there, which I think may be a better approach.
25-06-2024

I'm pretty sure these are instantiated. A `Species_` class generated for the benefit of `BoundMethodHandle` are sort of generic holders used in combination with the `LambdaForm` (which is more of the code/logic side of the code). `Species_L` holds one bound reference argument, `Species_LL` holds two, `Species_LI` holds a reference and an int and so on.
24-06-2024

Do these classes have objects created for them, or are they just used to generate code? If the latter, can you mark them as abstract? We have a future RFE to make abstract and interface classes not be allocated in class metaspace so these generated classes don't fill up class metaspace.
24-06-2024

JDK-8078629 is already fixed and I looked at the peak perf numbers on Octane. They look much better, but there are still some regressions (~10-20% on average). Should be evaluated. Also, startup/warmup impact of the switch to VM anon classes should be measured as well. It complicates LambdaForm compiled shapes (since BMHs are used everywhere), so it will run slower until the is compiled.
21-08-2015

Test "java/lang/invoke/LFCaching/LFGarbageCollectedTest.java" has been excluded because it fails because of this bug. See JDK-8068416. The test should be turned on again after this issue is fixed.
05-06-2015

Unless VM is able to constant fold field loads using MethodHandles (JDK-8078629), BMH$Species can't be loaded as VM anonymous classes.
24-04-2015