Unloading LambdaForm bytecode

John Rose john.r.rose at oracle.com
Tue Sep 9 01:29:46 UTC 2014


Hi Martin.

A few LFs are cached in 8u20, and many more will be in 8u40; those will not be unloaded.

A non-cached LF can be viewed as customized, to the exact MH that caused its creation.

It should be the case that a LF that is customized to LFs will be unloaded (with its bytecodes) as soon as the last reference to it goes away.

An indy instruction bound to a LF (via a call site and MH) will typically be the only reference to the LF, so if the class containing the indy goes away, the LF should go also.

LF bytecodes are loaded with Unsafe.defineAnonymousClass, which means that the class is not registered in any class loader or dictionary, but should get unloaded as soon as everybody drops the java.lang.Class for the LF bytecodes.  A MH with anonymous bytecodes indirectly refers to the java.lang.Class.

All that's to say that you should not have a storage leak if your classes are getting unloaded.  (And if you don't cache MHs, etc.)  If you have a leak, there's either an inadvertent reference keeping the MH stuff alive, or else there is a bug in the defineAnonymousClass mechanism.

(I can't remember offhand whether anonymous classes report unload events.  If the reporting is coupled to the system dictionary, then you won't get a report, since ACs don't affect the system dictionary.)

But.  The example you give below comes from MethodHandles.constant (a K combinator instance).  Those are cached, I think.  They also should not be numerous, since their types are erased to basic-types.

The string inside the dummy method is intended to be human-readable documentation of what the LF does.

In this example, the class Species_L is a bound method handle containing one reference field.  Its method argL0 returns that unique value.  (If it also had a second double field, the method would be Species_LD.argD1, etc.)  The receiver argument of this LF (a0) is a one-field Species_L which carries the constant K value in its argL0 field; when invoked, it returns that value.

If you have two LF classes with the same string, there might be bug.

— John

On Sep 8, 2014, at 4:54 PM, Martin Traverso <mtraverso at gmail.com> wrote:

> Do the generated bytecodes for LambdaForms ever get unloaded? In Presto (a distributed SQL engine) we generate bytecode on the fly for each query and use invokedynamic in a number of places as a way to link constants. We recently ran into a permgen leak (we run 7u45). Looking at the output of -verbose:class, I noticed a bunch of lines like these:
> 
>     [Loaded java.lang.invoke.LambdaForm$MH227/995942612 from java.lang.invoke.LambdaForm]
>     [Loaded java.lang.invoke.LambdaForm$MH228/489675590 from java.lang.invoke.LambdaForm]
>     [Loaded java.lang.invoke.LambdaForm$MH229/2095286826 from java.lang.invoke.LambdaForm]
>     [Loaded java.lang.invoke.LambdaForm$MH230/538456879 from java.lang.invoke.LambdaForm]
>     [Loaded java.lang.invoke.LambdaForm$MH231/1550961803 from java.lang.invoke.LambdaForm]
>     ...
> 
> We load our generated bytecode in standalone classloaders and it eventually gets unloaded. I never see an unload message for the LambdaForm classes, though.
> 
> This is what’s inside one of those classes. They all look similar:
> 
>     > javap -c 'LambdaForm$MH499.class'
> 
>     Compiled from "LambdaForm$MH499"
>     final class java.lang.invoke.LambdaForm$MH499 extends java.lang.invoke.LambdaForm {
>       static java.lang.Object identity(java.lang.Object);
>         Code:
>            0: aload_0       
>            1: checkcast     #12                 // class java/lang/invoke/BoundMethodHandle$Species_L
>            4: getfield      #16                 // Field java/lang/invoke/BoundMethodHandle$Species_L.argL0:Ljava/lang/Object;
>            7: astore_1      
>            8: ldc           #18                 // String CONSTANT_PLACEHOLDER_0 <<MethodHandle(Object)Object>>
>           10: checkcast     #20                 // class java/lang/invoke/MethodHandle
>           13: aload_1       
>           14: invokevirtual #23                 // Method java/lang/invoke/MethodHandle.invokeBasic:(Ljava/lang/Object;)Ljava/lang/Object;
>           17: areturn       
> 
>       static void dummy();
>         Code:
>            0: ldc           #27                 // String identity=Lambda(a0:L)=>{\n    t1:L=Species_L.argL0(a0:L);\n    t2:L=ValueConversions.identity(t1:L);t2:L}
>            2: pop           
>            3: return        
>     }
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev



More information about the mlvm-dev mailing list