synchronized方法的字節碼分析

首先編寫一段代碼將三種使用synchronized的形式都包含在裏面

在反編譯看看助記符代碼

public class syschoriznizedbytecodetest {
    Object a;
    public static synchronized void test1(){
        System.out.println("static synchrozied");
    }
    public synchronized void test2(){
        System.out.println("nostatic method syschronized");
    }
    public void test3(){
        synchronized (a){
            System.out.println("code block test");
        }
    }


}
我將一部分常量池和方法的一些代碼刪掉了,我們只看這幾個測試方法

  public static synchronized void test1();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String static synchrozied
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 6: 0
        line 7: 8

  public synchronized void test2();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #5                  // String nostatic method syschronized
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 9: 0
        line 10: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Lcom/nettylearn/Service/binarycode/syschoriznizedbytecodetest;

  public void test3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: aload_0
         1: getfield      #6                  // Field a:Ljava/lang/Object;
         4: dup
         5: astore_1
         6: monitorenter
         7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        10: ldc           #7                  // String code block test
        12: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        15: aload_1
        16: monitorexit
        17: goto          25
        20: astore_2
        21: aload_1
        22: monitorexit
        23: aload_2
        24: athrow
        25: return
      Exception table:
         from    to  target type
             7    17    20   any
            20    23    20   any
      LineNumberTable:
        line 12: 0
        line 13: 7
        line 14: 15
        line 15: 25
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      26     0  this   Lcom/nettylearn/Service/binarycode/syschoriznizedbytecodetest;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 20
          locals = [ class com/nettylearn/Service/binarycode/syschoriznizedbytecodetest, class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4
}
SourceFile: "syschoriznizedbytecodetest.java"


我們可以發現前兩種方式在字節碼上面只是對方法的標示添加了synchronized這個標記,而最後一個代碼塊的方式我們就可以很清晰的看到它使用了monitorenter和monitorexit兩個操作命令。

而且對於monitorexit還使用了兩次,這是因爲如果我們使用了print的io操作在io操作時可能會發生錯誤所以系統爲我們加了一個額外的monitorexit因爲如果出了錯誤就不會走到我們自己通過synchronized所產的那個monitorexit了,而且這裏面有一個goto命令也就是說如果沒有錯誤就會goto到return命令。

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