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