JDK-8168848 : Too many anonymous classes that aren't unloaded
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 9
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2016-10-27
  • Updated: 2025-04-24
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
Relates :  
Relates :  
Description
class hello {
    public static void main(String[] args) {
      {
        int var = 5;
        System.out.println("Hello World!" + var); // Display "Hello World!"
      }
      for (int i = 0; i < 100 ; i++) {
          // nuke the anonymous classes
          System.gc();
      }
    }
}

Creates 17 anonymous classes because of the concatenation of var.

Printing in Unsafe_Define_AnonymousClass:
There are 16 different ones of these:
Anonymous class java.lang.invoke.LambdaForm$BMH/249515771 created host class java.lang.invoke.LambdaForm

And one of these, which is added as a dependency to the application class loader:
Anonymous class java.lang.invoke.LambdaForm$MH/586617651 created host class java.lang.invoke.LambdaForm

This seems crazy inefficient.   Also need to figure out why the $BMH are never unloaded.

Comments
I don't see them anymore from this test program. I agree, I think this issue has been resolved.
24-04-2025

It should have been relieved by JDK-8336856. Can you try again [~coleenp]?
24-04-2025

If you run the above program with not-product JDK build and with these options: java -Xlog:class+load,class+unload -XX:+PrintSystemDictionaryAtExit hellolambdas There are six lambda classes like this that are loaded. I think they're hidden classes now: [0.344s][info][class,load] java.lang.invoke.LambdaForm$MH/0x0000000800bf0840 source: __JVM_LookupDefineClass__ And when the ClassLoaderDataGraph is printed at the end, and there are now 6 CLD for these classes that aren't unloaded: ClassLoaderData CLD: 0x00007fb2f0365c50, loader: 0x0000000000000000, loader_klass: 'bootstrap' { has a class holder claimed metaspace: 0x00007fb2f0365e40 handles count 2 dependencies 0} Should these LambdaForm classes be non weak hidden classes?
11-06-2020

Ok, I confused BMH LambdaForms with BMH$Species_*. The former are VMACs and latter are ordinary classes. We can definitely consider switching to Unsafe_DefineClass, but it's a tradeoff. You save some memory on per-class right away (by avoiding VMAC overhead), but in a longer term the downside is there's no way to unload the class. So, whether you actually save memory or not depends on the application. For LFs we don't strictly need VMACs, something more lightweight is enough (like Isolated Methods). But there are other VMAC usages like lambdas, which need full blown classes.
27-10-2016

> BMHs are not VMACs: they are ordinary classes injected into boot class path using Unsafe.defineClass(). There's an >RFE to experiment with using VMACs instead (JDK-8078602). The printing I added is done at the end of Unsafe_DefineAnonymousClass_impl, so they are VMACs. If they are NOT unloaded, and are still reachable, it would be better if they are Unsafe_DefineClass instead. Then they wouldn't create their own metaspace and ClassLoaderData object. These 17 VMACs are from a "final" image, not exploded build. I haven't studied this JEP yet. It's high on my todo list.
27-10-2016

I'm currently not working to reduce number of shapes/classes generated by ISC further, but as [~vlivanov] points out we're in better shape now than we were, but since a jlink plugin plays a role in that optimization story you'll see more VMACs if you run this on an exploded image than on a "final" image. There's also a JEP aimed at optimizing VMAC overhead: JDK-8158765
27-10-2016

Also, [~redestad] has been working on reducing amount of classes (VMACs) needed for LambdaForms (e.g., JDK-8165492, JDK-8163369) by either pre-generating them as methods during link-time (thus avoiding class loading at runtime) or by simplifying shapes of MH chains.
27-10-2016

Also, it's probable that VMACs you are seeing are still reachable: there's a method handle chain bound to invokedynamic call site for string concat.
27-10-2016

[~dholmes] String concatenation is indy-based in 9 + lambas are used in core libraries.
27-10-2016

Compilers don't use VMACs in any way. Reclassifying to java.lang.invoke.
27-10-2016

Why does simple String concatenation create ANY anonymous classes never mind 17 of them? Is this some lazy library initialization?
27-10-2016

Compiled LambdaForm caches are SoftReference-based. So, repeatedly doing GC isn't enough to evict them. SoftRefs were chosen deliberately (over WeakRefs), since LambdaForm construction & compilation is quite expensive. BMHs are not VMACs: they are ordinary classes injected into boot class path using Unsafe.defineClass(). There's an RFE to experiment with using VMACs instead (JDK-8078602).
27-10-2016

Assigned to compiler because they keep adding these but it really affects metaspace. Should these be added to the metaspace of the host class in some cases and not have their own metaspace?
27-10-2016