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 <mtrave...@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@openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to