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命令。

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