2016-12-24 31 views
-1

我一直在做一些关于Java字节码的个人研究,并且遇到了一些奇怪之处。如果我反编译this class,我发现参考Class.forName()挂在常量池中。但是,源代码中没有提及此方法。为什么Class.forName出现在这个类的字节码中?

我认为这段代码会导致javac发出一些动态加载类的代码,但我不知道为什么会发生这种情况。它让我觉得效率低下,但主要是我很好奇为什么会发生这种情况。

+5

为什么不发布该类,以及反编译的结果,其中包含令人惊讶的Class.forName()。这会阻止我们猜测。 –

+0

忘记勾选“回答您的问题”框时,我做到了这一点。我写了这个问题,我想到javap可能会指出它为什么会发生。想象我会把它发布给任何碰到它的人。 – monitorjbl

+0

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

回答

2

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$()方法不再需要。

+0

实际上,ldc保持不变,只是增加了引用class_info常量的能力。 – Antimony

+0

'ldc_w'是'ldc'的一个特殊变体,它允许寻址256个以上的常量池条目(或者超过前256个条目,更具体)。两者都可以引用自Java 5以来的'Class'条目(自Java 7以来可能引用'MethodType'或'MethodHandle';支持的条目类型列表将来可能会增长)。预Java 5代码的确切布局是编译器特定的。有些编译器生成的代码会将'Class'缓存在'static'字段中,以避免每次调用'forName'。 – Holger

相关问题