1. 程式人生 > >JAVA class檔案中的符號引用

JAVA class檔案中的符號引用

在java程式碼中,一個類可能使用另外類或者介面的欄位或者呼叫另外一個類的方法。
在編譯的時候,class檔案中是通過叫做"符號引用"的方式來實現的。
如下面的例子
public interface Intf {    
    public static String str = "abcde";
    public static int ival = new Random().nextInt();

}
public class T {
    public static int tint = Intf.ival;
}
class T編譯成class 檔案之後,利用javap -verbose 檢視class檔案,可以看到
在初始化static int tint的時候,從常量池的第12項取值
static {};
  Code:
   Stack=1, Locals=0, Args_size=0
   0:    getstatic    #12; //Field Intf.ival:I
   3:    putstatic    #17; //Field tint:I
   6:    return
  LineNumberTable:
   line 6: 0
   line 3: 6
常量池的第12項是一個符號引用,指向Intf的ival欄位。ival的值只能在執行的時候才能確定。
const #12 = Field    #13.#15;    //  Intf.ival:I
const #13 = class    #14;    //  Intf
在執行的時候會將符號引用解析為指向Intf記憶體地址的直接引用。

如果將class T改為如下,引用的是Intf的一個在編譯時候就可以確定的常量值。
通過檢視編譯後的class檔案,發現在T的class檔案中,是將str = "abcde";的值
"abcde"直接複製了一份放到了常量池中,沒有符號引用。
public class T {
    public static String tstr = Intf.str;
}
在初始化static int tint的時候,從常量池的第12項取值
static {};
  Code:
   Stack=1, Locals=0, Args_size=0
   0:    ldc    #12; //String abcde
   2:    putstatic    #14; //Field tstr:Ljava/lang/String;
   5:    return
  LineNumberTable:
   line 5: 0
   line 3: 5
常量池的第12項直接為"abcde"字串。
const #12 = String    #13;    //  abcde
const #13 = Asciz    abcde;

本文的測試是在SUN 的hotspot jvm環境中。

後面這種情況在classpath中甚至可以沒有Intf類檔案。