java – MethodHandles. lookup(). defineClass retention
MethodHandles. Lookup. Defineclass generates a new class from the byte array at run time
Under what circumstances can the returned class be garbage collected? Is it retained for the lifetime of the class loader associated with the lookup object, or can it be garbage collected if the class object is no longer referenced?
Solution
Through methodhandles Lookup. Classes created by defineclass are registered in the definition class loader like any other class and can be referenced by name like ordinary classes Before parsing these classes, they can even replace statically compiled classes, as shown in the following example:
import java.lang.invoke.MethodHandles; import java.nio.charset.StandardCharsets; public class LookupDynamicClass { public static void main(String[] args) throws illegalaccessexception { MethodHandles.Lookup lookup = MethodHandles.lookup(); lookup.defineClass(("Êþº¾\0\0\0005\0\26\11\0\11\0\12\10\0\13\12\0\14\0" +"\15\7\0\16\7\0\17\1\0\3foo\1\0\3()V\1\0\4Code\7\0\20\14\0\21\0\22\1\0" +"\30hello from dynamic class\7\0\23\14\0\24\0\25\1\0\4Lazy\1\0\20java/" +"lang/Object\1\0\20java/lang/System\1\0\3out\1\0\25Ljava/io/PrintStream;" +"\1\0\23java/io/PrintStream\1\0\7println\1\0\25(Ljava/lang/String;)V\6\0" +"\0\4\0\5\0\0\0\0\0\1\0\11\0\6\0\7\0\1\0\10\0\0\0\25\0\2\0\0\0\0\0\11²\0" + "\1\22\2¶\0\3±\0\0\0\0\0\0").getBytes(StandardCharsets.ISO_8859_1)); Lazy.foo(); } } interface Lazy { static void foo() { } }
Try it online
This example dynamically defines a lazy class whose foo () method will print hello. 0 from the dynamic class when called
On JVMs like hotspot, the symbolic reference "lazy" is lazily resolved, that is, trying to call lazy Foo (), this will end up in dynamically defined classes For JVMs eager to resolve symbol references, when calling methodhandles Lookup. When defining class, the lazy class already exists, so a linkageerror with a message such as "trying to define lazy repeatedly" will be thrown
In other words, these dynamically generated classes share the same namespace (class loading context) as statically compiled classes Register in the class loader like ordinary classes. Only when the defined class loader becomes inaccessible (including all defined classes), can they get garbage collection, just like ordinary classes