synchronized 字节码分析
我们先来看一下一个简单的方法
public class MyTest02 { int x = 0;
public void setX(int x) { this.x = x; } }
|
使用 javap -v com.cuzz.jvm.bytecode.MyTest02
命令,找到 setX
方法
public void setX(int); descriptor: (I)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: iload_1 2: putfield #2 // Field x:I 5: return LineNumberTable: line 12: 0 line 13: 5 LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lcom/cuzz/jvm/bytecode/MyTest02; 0 6 1 x I
|
如果我们在方法中添加 synchronzied
关键字
public class MyTest02 { int x = 0;
public synchronized void setX(int x) { this.x = x; } }
|
我们再反编译一下
public synchronized void setX(int); descriptor: (I)V flags: ACC_PUBLIC, ACC_SYNCHRONIZED Code: stack=2, locals=2, args_size=2 0: aload_0 1: iload_1 2: putfield #2 // Field x:I 5: return LineNumberTable: line 12: 0 line 13: 5 LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lcom/cuzz/jvm/bytecode/MyTest02; 0 6 1 x I
|
对比这两个反编译的结果,我们发现在 flags 中多了 ACC_SYNCHRONIZED
,不会出现 monitorenter 和 monitorexit。
如果我们是在方法体重添加 synchronized
关键字
public class MyTest02 { String lock = "lock"; int x = 0;
public int getX() { synchronized (lock) { return x; } } }
|
我们反编译一下 找到 getX
方法
public int getX(); descriptor: ()I flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: aload_0 1: getfield #3 // Field lock:Ljava/lang/String; 4: dup 5: astore_1 6: monitorenter 7: aload_0 8: getfield #4 // Field x:I 11: aload_1 12: monitorexit 13: ireturn 14: astore_2 15: aload_1 16: monitorexit 17: aload_2 18: athrow Exception table: from to target type 7 13 14 any 14 17 14 any LineNumberTable: line 17: 0 line 18: 7 line 19: 14 LocalVariableTable: Start Length Slot Name Signature 0 19 0 this Lcom/cuzz/jvm/bytecode/MyTest02; StackMapTable: number_of_entries = 1 frame_type = 255 /* full_frame */ offset_delta = 14 locals = [ class com/cuzz/jvm/bytecode/MyTest02, class java/lang/Object ] stack = [ class java/lang/Throwable ]
|
在 6 中出现 monitorenter,在 16 中出现 moniterexit