2004-09-30
第六章:jvm虛擬指令集
6.1假定:“必須”的含義
對于jvm指令的一些“必須”的要求,在運行期要求javaclass的結構是滿足約束的,對于不滿足約束的情況,jvm的行為是未定義的。
6.2保留操作碼
在java class文件中使用的指令操作碼,有三個操作碼是保留的,供java虛擬機內部使用。
254(0xfe)和255(0xff),分別有助記符impdep1和impdep2,目的是在軟件或者硬件實現的特定功能提供“后門”或陷阱。
202(0xca),有助記符breakpoint,目的是由調試程序使用來實現斷點。
6.3虛擬機錯誤
當內部錯誤或者資源限制導致java語言語義不能實現時,jvm拋出一個VirtualMachineError類的子類的實例。jvm規范不規定和語言拋出的時間和地點。
6.4jvm指令集
我不一一例舉各種指令的操作碼和用法,需要時去查就行了。
第七章 為jvm編譯
7.1范例格式
java編譯成為class文件之后,以類匯編的jvm操作指令方式存在,jdk自帶的javap程序具有這樣的功能,將class文件翻譯為這樣的指令集。
下面是我測試的一個實例:
源文件為test.java
public class test {
??? public static String a = "";
??? public int i =0;
??? public test() {
??????? int i=0;
??????? String a = "xyz";
??? }
}
編譯完成為test.class,用javap生成之后輸出結果為:
C:\JBuilderX\jdk1.4\bin>javap -c? -classpath "c:/" test
Compiled from "test.java"
public class test extends java.lang.Object{
public static java.lang.String a;
public int i;
static {};
? Code:
?? 0:?? ldc???? #4; //String
?? 2:?? putstatic?????? #5; //Field a:Ljava/lang/String;
?? 5:?? nop
?? 6:?? return
public test();
? Code:
?? 0:?? aload_0
?? 1:?? invokespecial?? #1; //Method java/lang/Object."":()V
?? 4:?? aload_0
?? 5:?? iconst_0
?? 6:?? putfield??????? #2; //Field i:I
?? 9:?? iconst_0
?? 10:? istore_1
?? 11:? ldc???? #3; //String xyz
?? 13:? astore_2
?? 14:? nop
?? 15:? return
}
7.2常數、局部變量和控制結構的使用
jvm是面向棧的,大多數操作都是從當前框架的操作數棧中取得操作數。
7。3運算
jvm一般在操作數棧上進行運算,即從棧中取操作數,并將結果存入操作數棧中。
7。4訪問常數池
byte,char,short,以及小int值都可以通過立即數的方式編譯在method的code中,但是int,long,float,double,以及string實例的引用,就需要對常數池進行訪問了。使用ldc,ldc_w,ldc2_w指令管理。
7.5更多控制范例
可供查閱
7。6接收參數
如果向java實例方法傳遞了n個參數,它們被接收,按約定,框架的編號1到n的局部變量為新的方法調用創建,順序為接收的順序。
7。7調用方法
對java實例方法的調用,是在對象的運行期類型上調度的。用invokevirtual實現,將其參數取做對常數池表項的索引,給出對象的類類型的完整限定符名稱,再調用方法的名稱和方法的描述符。
對java靜態(類)方法的調用,無需傳遞類實例,其余和實例方法相似,用invokespecial方法實現。
invokespecail指令用于調用實例初始化方法。超類方法和調用private方法。
7。8處理類實例
構建一個類實例的過程,在建立對象及其實例域之后,用invokespecial調用相應構造函數對應的方法來初始化對象。
對對象域的訪問用getfield和putfield指令完成。
7。9數組
主要講的是數組操作的相關jvm指令,如:newarray,過一遍,可以查閱。
7。10編譯開關
對于java的switch指令,jvm有對應的兩種指令:tableswitch,lookupswitch.
tableswitch指定取值范圍,而lookupswitch并不指定取值范圍,兩者如何選擇完全由效率選擇決定。
7。11對操作數棧的操作
jvm有大量的指令補充,將操作數棧的內容作為無類型字或成對的無類型字操縱。便于jvm虛擬機指令的靈活組成。
如dup,dup_x2等,都是對字或者雙字進行操作。
7。12拋出或者處理異常
jvm中try...catch塊的處理對于jvm指令處理是透明的,輔助控制是由異常表來完成的,由異常表來決定到哪里去調用處理,哪些部分的異常是受控的。
7。13編譯finally
try.....finally語句與try-catch相似,只是其輔助控制是由指令jsr(子例程調用)顯式的表示,在jsr調用之前,將下一指令的地址壓入棧中。而異常表只控制try塊的范圍。
7。14同步
jvm用monitorenter和monitorexit指令對同步提供顯式支持。而java常用sychronized方法。
sychronized“方法”通常不是用monitorenter和monitorexit指令實現的。往往是由“方法調用指令”檢查常數池里的ACC_SYCHRONIZED標志
但monitorenter和monitorexit指令是為了支持sychronized“語句”而存在的。
注意這里的方法和語句的區別。
語句實例如下:test.java
public class test {
? public test() {
? }
? public static void main(String[] args) {
??? synchronized(new Object()){
??????? int i = 0;
??? }
? }
}
編譯完的結果:
C:\JBuilderX\bin>javap -c? -classpath "d:/epm40/classes" test
Compiled from "test.java"
public class test extends java.lang.Object{
public test();
? Code:
?? 0:?? aload_0
?? 1:?? invokespecial?? #1; //Method java/lang/Object."":()V
?? 4:?? nop
?? 5:?? return
public static void main(java.lang.String[]);
? Code:
?? 0:?? new???? #2; //class Object
?? 3:?? dup
?? 4:?? invokespecial?? #1; //Method java/lang/Object."":()V
?? 7:?? dup
?? 8:?? astore_1
?? 9:?? monitorenter
?? 10:? iconst_0
?? 11:? istore_2
?? 12:? nop
?? 13:? aload_1
?? 14:? monitorexit
?? 15:? goto??? 23
?? 18:? astore_3
?? 19:? aload_1
?? 20:? monitorexit
?? 21:? aload_3
?? 22:? athrow
?? 23:? nop
?? 24:? return
? Exception table:
?? from?? to? target type
??? 10??? 15??? 18?? any
??? 18??? 21??? 18?? any
}
而synchronized方法編譯沒有特殊之處,只是在方法名上加了synchronzied字樣。