通过
MethodHandles.Lookup.defineClass创建的类与任何其他类一样在定义类加载程序中注册,并且可以像普通类一样通过名称引用,而不是
defineHiddenClass(…)
,可用于定义未在类加载器中注册的类,还可以访问查找类的
private
成员,类似于旧的非标准特性sun.misc.Unsafe.defineAnonymousClass
公共类LookupHiddenClass{
var lookup=MethodHandles.lookup();
lookup=lookup.defineHiddenClass((“\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”
+“\27hello来自隐藏类\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“).getBytes(StandardCharsets.ISO\u 8859\u 1),true);
var r=新幻影参考<&燃气轮机(lookup.lookupClass(),q);
查找=空;
do System.gc();而(q.remove(1000)!=r) ;
System.out.println(“收集的类”);
}
}
来自隐藏类的hello
在线试用
此示例动态定义
Lazy
谁的班级
foo()
方法将打印
hello from dynamic class
在类似HotSpot的jvm上,符号引用
在尝试调用
Lazy.foo()
则这将在动态定义的类中结束。对于渴望解析符号引用的jvm
懒惰的
当
被调用,因此
LinkageError
如果出现类似以下消息,将抛出重复的Lazy定义。
引入JDK15
它可以用来定义未在类装入器中注册的类,也可以访问
private
查找类的成员,类似于旧的非标准功能
sun.misc.Unsafe.defineAnonymousClass
行为由
ClassOption
参数。
-
NESTMATE
允许访问
私有的
查找类的成员及其嵌套成员(通常是内部类)
-
STRONG
防止类被卸载,直到类加载器变得不可访问,尽管我不知道为什么有人会想要这个。如果没有这个选项,一旦不存在对隐藏类的引用,它就可以被垃圾收集并卸载。
public class LookupHiddenClass {
public static void main(String[] args) throws Throwable {
var lookup = MethodHandles.lookup();
lookup = lookup.defineHiddenClass(("Ãþº¾\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"
+"\27hello from hidden 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), true);
lookup.findStatic(lookup.lookupClass(), "foo", MethodType.methodType(void.class))
.invokeExact();
var q = new ReferenceQueue<Class<?>>();
var r = new PhantomReference<>(lookup.lookupClass(), q);
lookup = null;
do System.gc(); while(q.remove(1000) != r);
System.out.println("class collected");
}
}
System.gc()
将执行实际的垃圾收集,也不会收集特定的对象,使用OpenJDKs默认配置可重复打印
hello from hidden class
class collected