Unloading LambdaForm bytecode

Martin Traverso mtraverso at gmail.com
Tue Sep 9 07:11:22 UTC 2014


Hi John,

Thanks for the detailed explanation.

I ran a few additional experiments after I wrote a simpler program to try
to reproduce the issue. I don't see the permgen leak, so something else
must be causing it in Presto. I do see the "Loaded..." messages without a
corresponding "Unloaded...", so your hypothesis about that happening for
anonymous classes seems likely. Interestingly, it has another side-effect:
the "Loaded classes" counter in VisualVM and in the ClassLoadingMXBean
don't seem to work correctly under this scenario.

It also reproduces the issue I mentioned regarding seemingly duplicate LFs.
The code is here if you want to take a quick look:
https://github.com/martint/lftest. The weird behavior goes away if I change
the indy callsite to return Object instead of String

Thanks!
Martin


On Mon, Sep 8, 2014 at 6:29 PM, John Rose <john.r.rose at oracle.com> wrote:

> 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
>
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20140909/f7766ba7/attachment-0001.html>


More information about the mlvm-dev mailing list