2016-12-24 45 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

相關問題