java反编译查看synchronized指令

  • java封装的太好了,导致我们只能看到表面的东西,要想更深层次了解原理有一个东西要用到就是javap 反编译.class文件,看到指令集

下面结合synchronized 关键字底层原理熟悉 javap用法

  • 第一创建一个类

public class test {
    public synchronized void test1(){

    }

    public void test2(){
        synchronized(this) {
            int i = 0;
            i++;
        }
    }

    public void test3(){
        synchronized(test.class) {
            int i = 0;
            i++;
        }
    }
}

然后用javac命令编译
javac test.java 生成test.class

然后用javap -v test.class 反编译出如下结果

Last modified 2022-2-28; size 546 bytes
  MD5 checksum 3a0c6ab13146d967a1782810ffe7e796
  Compiled from "test.java"
public class com.test.eventtest.test
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#17         // java/lang/Object."<init>":()V
   #2 = Class              #18            // com/test/eventtest/test
   #3 = Class              #19            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               test1
   #9 = Utf8               test2
  #10 = Utf8               StackMapTable
  #11 = Class              #18            // com/test/eventtest/test
  #12 = Class              #19            // java/lang/Object
  #13 = Class              #20            // java/lang/Throwable
  #14 = Utf8               test3
  #15 = Utf8               SourceFile
  #16 = Utf8               test.java
  #17 = NameAndType        #4:#5          // "<init>":()V
  #18 = Utf8               com/test/eventtest/test
  #19 = Utf8               java/lang/Object
  #20 = Utf8               java/lang/Throwable
{
  public com.test.eventtest.test();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public synchronized void test1();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 6: 0

  public void test2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: aload_0
         1: dup
         2: astore_1
         3: monitorenter
         4: iconst_0
         5: istore_2
         6: iinc          2, 1
         9: aload_1
        10: monitorexit
        11: goto          19
        14: astore_3
        15: aload_1
        16: monitorexit
        17: aload_3
        18: athrow
        19: return
      Exception table:
         from    to  target type
             4    11    14   any
            14    17    14   any
      LineNumberTable:
        line 9: 0
        line 10: 4
        line 11: 6
        line 12: 9
        line 13: 19
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 14
          locals = [ class com/test/eventtest/test, class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4

  public void test3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: ldc           #2                  // class com/test/eventtest/test
         2: dup
         3: astore_1
         4: monitorenter
         5: iconst_0
         6: istore_2
         7: iinc          2, 1
        10: aload_1
        11: monitorexit
        12: goto          20
        15: astore_3
        16: aload_1
        17: monitorexit
        18: aload_3
        19: athrow
        20: return
      Exception table:
         from    to  target type
             5    12    15   any
            15    18    15   any
      LineNumberTable:
        line 16: 0
        line 17: 5
        line 18: 7
        line 19: 10
        line 20: 20
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 15
          locals = [ class com/test/eventtest/test, class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4
}
SourceFile: "test.java"

可以看出加在方法上 编译会添加 flags: ACC_SYNCHRONIZED

添加到代码块上,编译会添加指令 monitorenter monitorexit ,这里实则就是用到了引用计数, monitor为0 的时候可以进入,当别的线程 monitorenter 引用计数+1,此线程只能等待。从而实现线程同步。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
请叫我西瓜瓜君的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容