Java字節碼new之後爲什麼會有dup

在看《深入理解Java虛擬機:JVM高級特性與最佳實踐(第二版)》這本書時,有幾處的字節碼在new之後會緊接着出現dup指令,我麼以書中253頁的字節碼爲例,說明dup指令的作用。

其中Java代碼爲:

public class DynamicDispatch {

	static abstract class Human {
		protected abstract void sayHello();
	}

	static class Man extends Human {
		@Override
		protected void sayHello() {
			System.out.println("man say hello");
		}
	}

	static class Woman extends Human {
		@Override
		protected void sayHello() {
			System.out.println("woman say hello");
		}
	}

	public static void main(String[] args) {
		Human man = new Man();
		Human woman = new Woman();
		man.sayHello();
		woman.sayHello();
		man = new Woman();
		man.sayHello();
	}
}

對應的字節碼爲:

 public static void main(java.lang.String[]);
   Code:
      0: new           #16 // class jvm/fenixsoft/DynamicDispath$Man
      3: dup
      4: invokespecial #18 // Method jvm/fenixsoft/DynamicDispach$Man."<init>":()V
      7: astore_1
      8: new           #19 // class jvm/fenixsoft/DynamicDispath$Woman
     11: dup
     12: invokespecial #21 // Method jvm/fenixsoft/DynamicDispach$Woman."<init>":()V
     15: astore_2
     16: aload_1
     17: invokevirtual #22 // Method jvm/fenixsoft/DynamicDispach$Human.sayHello:()V
     20: aload_2
     21: invokevirtual #22 // Method jvm/fenixsoft/DynamicDispach$Human.sayHello:()V
     24: new           #19 // class jvm/fenixsoft/DynamicDispath$Woman
     27: dup
     28: invokespecial #21 // Method jvm/fenixsoft/DynamicDispach$Woman."<init>":()V
     31: astore_1
     32: aload_1
     33: invokevirtual #22 // Method jvm/fenixsoft/DynamicDispach$Human.sayHello:()V
     36: return

關於dup指令的作用,在《深入理解Java虛擬機》這本書中是這麼描述的。這是一個操作數棧管理指令,負責複製棧頂(注意,這個棧指的是操作數棧)一個或者兩個數值並將複製值或雙份的複製值重新壓人棧頂。

簡單理解就是給操作數棧棧頂的元素弄了一個備份。

那麼爲什麼要進行備份呢?

一開始是new指令在堆上分配了內存並向操作數棧壓入了指向這段內存的引用,之後dup指令又備份了一份,那麼操作數棧頂就有兩個,再後是調用invokespecial #18指令進行初始化,此時會消耗一個引用作爲傳給構造器的“this”參數,那麼還剩下一個引用,會被astore_1指令存儲到局部變量表中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章