【dup】和【pop】

dup:java

複製棧頂元素並壓入棧程序員

 pop:this

出棧操做code

代碼對象

public class JvmTest1{
    public static void testMethod(){
    new JvmTest1(); 
    }
}

編譯字節碼文件內存

javap -c JvmTest1.class
Compiled from "JvmTest1.java"
public class JvmTest1 {
  public JvmTest1();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void testMethod();
    Code:
       0: new           #2                  // class JvmTest1
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: pop
       8: return
}

1) 其中new指令在java堆上爲JvmTest1對象分配內存空間,並將地址壓入操做數棧頂;ci

2) 而後dup指令爲複製操做數棧頂值,並將其壓入棧頂,也就是說此時操做數棧上有連續相同的兩個對象地址;編譯器

3) invokespecial指令調用實例初始化方法<init>:()V,注意這個方法是一個實例方法,因此須要從操做數棧頂彈出一個this引用,也就是說這一步會彈出一個以前入棧的對象地址;it

4) 在調用完實例初始化方法後,將重複的實例引用又pop出棧了。由於我只new了一個JvmTest1對象,並無使用。不過這種狀況基本不會出如今咱們的代碼中,由於咱們建立的每個對象都應該是有用的。編譯

5) 最後由return指令結束方法。

從上面的五個步驟中能夠看出,須要從棧頂彈出兩個實例對象的引用,這就是爲何會在new指令下面有一個dup指令,其實對於每個new指令來講通常編譯器都會在其下面生成一個dup指令,這是由於實例的初始化方法確定須要用到一次,而後第二個留給程序員使用,例如給變量賦值,拋出異常等,若是咱們不用,那編譯器也會生成dup指令,在初始化方法調用完成後再從棧頂pop出來。

相關文章
相關標籤/搜索