我一直在做一些关于Java字节码的个人研究,并且遇到了一些奇怪之处。如果我反编译this class,我发现参考Class.forName()
挂在常量池中。但是,源代码中没有提及此方法。为什么Class.forName出现在这个类的字节码中?
我认为这段代码会导致javac发出一些动态加载类的代码,但我不知道为什么会发生这种情况。它让我觉得效率低下,但主要是我很好奇为什么会发生这种情况。
我一直在做一些关于Java字节码的个人研究,并且遇到了一些奇怪之处。如果我反编译this class,我发现参考Class.forName()
挂在常量池中。但是,源代码中没有提及此方法。为什么Class.forName出现在这个类的字节码中?
我认为这段代码会导致javac发出一些动态加载类的代码,但我不知道为什么会发生这种情况。它让我觉得效率低下,但主要是我很好奇为什么会发生这种情况。
与javap
拆解代码后,我注意到,有不在源代码中存在的方法:
static java.lang.Class class$(java.lang.String);
Code:
0: aload_0
1: invokestatic #1 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
4: areturn
5: astore_1
6: new #3 // class java/lang/NoClassDefFoundError
9: dup
10: invokespecial #4 // Method java/lang/NoClassDefFoundError."<init>":()V
13: aload_1
14: invokevirtual #5 // Method java/lang/NoClassDefFoundError.initCause:(Ljava/lang/Throwable;)Ljava/lang/Throwable;
17: athrow
Exception table:
from to target type
0 4 5 Class java/lang/ClassNotFoundException
它看起来像这样的字节码生成编译版本< JDK1.5每当在代码 [1]中引用类别字面量时。基本上,这个:
if (getClass() == Level.class) {}
变成这样:
if (getClass() == class$("org.apache.log4j.Level")) {}
和class$()
看起来是这样的:
static Class class$(java.lang.String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
throw new NoClassDefFoundError();
}
}
显然,在JDK1.5中,ldc_w
指令被赋予加载能力类常量和class$()
方法不再需要。
为什么不发布该类,以及反编译的结果,其中包含令人惊讶的Class.forName()。这会阻止我们猜测。 –
忘记勾选“回答您的问题”框时,我做到了这一点。我写了这个问题,我想到javap可能会指出它为什么会发生。想象我会把它发布给任何碰到它的人。 – monitorjbl
2016年12月25日,当Java 1.4 [2008年10月30日终止](http://www.oracle.com/)时,您正在回答*** Java 1.4 ***问题technetwork/java/javase/index-jsp-138567.html),超过8年前?你是否渴望[自学者]徽章?(http://stackoverflow.com/help/badges/14/self-learner)徽章?这个问题/答案已经过时了,所以我必须同时使用*“无用”*。 – Andreas