• JVM synchronized关键字所生成的字节码


    一、创建测试类

    package com.example.jvm.bytecode;
    
    public class MyTest2 {
    
        String str = "Welcome";
    
        private  int x = 5;
    
        public static  Integer in = 10;
    
        public static void main(String[] args) {
            MyTest2 myTest2 = new MyTest2();
    
            myTest2.setX(8);
    
            in = 20;
        }
    
        public void setX(int x){
            this.x = x;
        }
      }
    

     

    反编译MyTest2.class文件

    D:workspacestudy jvm_demouildclassesjavamaincomexamplejvmytecode>javap -verbose MyTest2.class
    Classfile /D:/workspace/study/ jvm_demo/build/classes/java/main/com/example/jvm/bytecode/MyTest2.class
      Last modified 2019-6-26; size 847 bytes
      MD5 checksum d8f82e3e7255d9a738591c52d3a5417b
      Compiled from "MyTest2.java"
    public class com.example.jvm.bytecode.MyTest2
      SourceFile: "MyTest2.java"
      minor version: 0
      major version: 51
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #10.#34        //  java/lang/Object."<init>":()V
       #2 = String             #35            //  Welcome
       #3 = Fieldref           #5.#36         //  com/example/jvm/bytecode/MyTest2.str:Ljava/lang/String;
       #4 = Fieldref           #5.#37         //  com/example/jvm/bytecode/MyTest2.x:I
       #5 = Class              #38            //  com/example/jvm/bytecode/MyTest2
       #6 = Methodref          #5.#34         //  com/example/jvm/bytecode/MyTest2."<init>":()V
       #7 = Methodref          #5.#39         //  com/example/jvm/bytecode/MyTest2.setX:(I)V
       #8 = Methodref          #40.#41        //  java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       #9 = Fieldref           #5.#42         //  com/example/jvm/bytecode/MyTest2.in:Ljava/lang/Integer;
      #10 = Class              #43            //  java/lang/Object
      #11 = Utf8               str
      #12 = Utf8               Ljava/lang/String;
      #13 = Utf8               x
      #14 = Utf8               I
      #15 = Utf8               in
      #16 = Utf8               Ljava/lang/Integer;
      #17 = Utf8               <init>
      #18 = Utf8               ()V
      #19 = Utf8               Code
      #20 = Utf8               LineNumberTable
      #21 = Utf8               LocalVariableTable
      #22 = Utf8               this
      #23 = Utf8               Lcom/example/jvm/bytecode/MyTest2;
      #24 = Utf8               main
      #25 = Utf8               ([Ljava/lang/String;)V
      #26 = Utf8               args
      #27 = Utf8               [Ljava/lang/String;
      #28 = Utf8               myTest2
      #29 = Utf8               setX
      #30 = Utf8               (I)V
      #31 = Utf8               <clinit>
      #32 = Utf8               SourceFile
      #33 = Utf8               MyTest2.java
      #34 = NameAndType        #17:#18        //  "<init>":()V
      #35 = Utf8               Welcome
      #36 = NameAndType        #11:#12        //  str:Ljava/lang/String;
      #37 = NameAndType        #13:#14        //  x:I
      #38 = Utf8               com/example/jvm/bytecode/MyTest2
      #39 = NameAndType        #29:#30        //  setX:(I)V
      #40 = Class              #44            //  java/lang/Integer
      #41 = NameAndType        #45:#46        //  valueOf:(I)Ljava/lang/Integer;
      #42 = NameAndType        #15:#16        //  in:Ljava/lang/Integer;
      #43 = Utf8               java/lang/Object
      #44 = Utf8               java/lang/Integer
      #45 = Utf8               valueOf
      #46 = Utf8               (I)Ljava/lang/Integer;
    {
      java.lang.String str;
        flags:
    
      public static java.lang.Integer in;
        flags: ACC_PUBLIC, ACC_STATIC
    
      public com.example.jvm.bytecode.MyTest2();
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: aload_0
             5: ldc           #2                  // String Welcome
             7: putfield      #3                  // Field str:Ljava/lang/String;
            10: aload_0
            11: iconst_5
            12: putfield      #4                  // Field x:I
            15: return
          LineNumberTable:
            line 3: 0
            line 5: 4
            line 7: 10
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      16     0  this   Lcom/example/jvm/bytecode/MyTest2;
    
      public static void main(java.lang.String[]);
        flags: ACC_PUBLIC, ACC_STATIC
        Code:
          stack=2, locals=2, args_size=1
             0: new           #5                  // class com/example/jvm/bytecode/MyTest2
             3: dup
             4: invokespecial #6                  // Method "<init>":()V
             7: astore_1
             8: aload_1
             9: bipush        8
            11: invokevirtual #7                  // Method setX:(I)V
            14: bipush        20
            16: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
            19: putstatic     #9                  // Field in:Ljava/lang/Integer;
            22: return
          LineNumberTable:
            line 12: 0
            line 14: 8
            line 16: 14
            line 17: 22
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      23     0  args   [Ljava/lang/String;
                   8      15     1 myTest2   Lcom/example/jvm/bytecode/MyTest2;
    
      public void setX(int);
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: iload_1
             2: putfield      #4                  // Field x:I
             5: return
          LineNumberTable:
            line 20: 0
            line 21: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0       6     0  this   Lcom/example/jvm/bytecode/MyTest2;
                   0       6     1     x   I
    
      static {};
        flags: ACC_STATIC
        Code:
          stack=1, locals=0, args_size=0
             0: bipush        10
             2: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
             5: putstatic     #9                  // Field in:Ljava/lang/Integer;
             8: return
          LineNumberTable:
            line 9: 0
    }
    

      

    二、将setX改为private

    此时需要使用javap -verbose -p  MyTest2.class才能显示私有方法

    D:workspacestudy jvm_demouildclassesjavamaincomexamplejvmytecode>javap -verbose -p  MyTest2.class
    Classfile /D:/workspace/study/ jvm_demo/build/classes/java/main/com/example/jvm/bytecode/MyTest2.class
      Last modified 2019-6-27; size 847 bytes
      MD5 checksum f9ed848bb768588b932c395b40c509a8
      Compiled from "MyTest2.java"
    public class com.example.jvm.bytecode.MyTest2
      SourceFile: "MyTest2.java"
      minor version: 0
      major version: 51
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #10.#34        //  java/lang/Object."<init>":()V
       #2 = String             #35            //  Welcome
       #3 = Fieldref           #5.#36         //  com/example/jvm/bytecode/MyTest2.str:Ljava/lang/String;
       #4 = Fieldref           #5.#37         //  com/example/jvm/bytecode/MyTest2.x:I
       #5 = Class              #38            //  com/example/jvm/bytecode/MyTest2
       #6 = Methodref          #5.#34         //  com/example/jvm/bytecode/MyTest2."<init>":()V
       #7 = Methodref          #5.#39         //  com/example/jvm/bytecode/MyTest2.setX:(I)V
       #8 = Methodref          #40.#41        //  java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       #9 = Fieldref           #5.#42         //  com/example/jvm/bytecode/MyTest2.in:Ljava/lang/Integer;
      #10 = Class              #43            //  java/lang/Object
      #11 = Utf8               str
      #12 = Utf8               Ljava/lang/String;
      #13 = Utf8               x
      #14 = Utf8               I
      #15 = Utf8               in
      #16 = Utf8               Ljava/lang/Integer;
      #17 = Utf8               <init>
      #18 = Utf8               ()V
      #19 = Utf8               Code
      #20 = Utf8               LineNumberTable
      #21 = Utf8               LocalVariableTable
      #22 = Utf8               this
      #23 = Utf8               Lcom/example/jvm/bytecode/MyTest2;
      #24 = Utf8               main
      #25 = Utf8               ([Ljava/lang/String;)V
      #26 = Utf8               args
      #27 = Utf8               [Ljava/lang/String;
      #28 = Utf8               myTest2
      #29 = Utf8               setX
      #30 = Utf8               (I)V
      #31 = Utf8               <clinit>
      #32 = Utf8               SourceFile
      #33 = Utf8               MyTest2.java
      #34 = NameAndType        #17:#18        //  "<init>":()V
      #35 = Utf8               Welcome
      #36 = NameAndType        #11:#12        //  str:Ljava/lang/String;
      #37 = NameAndType        #13:#14        //  x:I
      #38 = Utf8               com/example/jvm/bytecode/MyTest2
      #39 = NameAndType        #29:#30        //  setX:(I)V
      #40 = Class              #44            //  java/lang/Integer
      #41 = NameAndType        #45:#46        //  valueOf:(I)Ljava/lang/Integer;
      #42 = NameAndType        #15:#16        //  in:Ljava/lang/Integer;
      #43 = Utf8               java/lang/Object
      #44 = Utf8               java/lang/Integer
      #45 = Utf8               valueOf
      #46 = Utf8               (I)Ljava/lang/Integer;
    {
      java.lang.String str;
        flags:
    
      private int x;
        flags: ACC_PRIVATE
    
      public static java.lang.Integer in;
        flags: ACC_PUBLIC, ACC_STATIC
    
      public com.example.jvm.bytecode.MyTest2();
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: aload_0
             5: ldc           #2                  // String Welcome
             7: putfield      #3                  // Field str:Ljava/lang/String;
            10: aload_0
            11: iconst_5
            12: putfield      #4                  // Field x:I
            15: return
          LineNumberTable:
            line 3: 0
            line 5: 4
            line 7: 10
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      16     0  this   Lcom/example/jvm/bytecode/MyTest2;
    
      public static void main(java.lang.String[]);
        flags: ACC_PUBLIC, ACC_STATIC
        Code:
          stack=2, locals=2, args_size=1
             0: new           #5                  // class com/example/jvm/bytecode/MyTest2
             3: dup
             4: invokespecial #6                  // Method "<init>":()V
             7: astore_1
             8: aload_1
             9: bipush        8
            11: invokespecial #7                  // Method setX:(I)V
            14: bipush        20
            16: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
            19: putstatic     #9                  // Field in:Ljava/lang/Integer;
            22: return
          LineNumberTable:
            line 12: 0
            line 14: 8
            line 16: 14
            line 17: 22
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      23     0  args   [Ljava/lang/String;
                   8      15     1 myTest2   Lcom/example/jvm/bytecode/MyTest2;
    
      private void setX(int);
        flags: ACC_PRIVATE
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: iload_1
             2: putfield      #4                  // Field x:I
             5: return
          LineNumberTable:
            line 20: 0
            line 21: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0       6     0  this   Lcom/example/jvm/bytecode/MyTest2;
                   0       6     1     x   I
    
      static {};
        flags: ACC_STATIC
        Code:
          stack=1, locals=0, args_size=0
             0: bipush        10
             2: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
             5: putstatic     #9                  // Field in:Ljava/lang/Integer;
             8: return
          LineNumberTable:
            line 9: 0
    }
    View Code

    三、现在将setX方法增加synchronized 修饰符

    private synchronized void setX(int x)
    反编译后无synchronized和有synchronized的区别如下图:

    
    

    四、在类中增加test方法,方法里面使用了synchronize

        private void test(String str){
            synchronized (obj){
                System.out.println("hello world");
            }
        }
    

      反编译后如下:

     private void test(java.lang.String);
        flags: ACC_PRIVATE
        Code:
          stack=2, locals=4, args_size=2
             0: aload_0
             1: getfield      #6                  // Field obj:Ljava/lang/Object;
             4: dup
             5: astore_2
             6: monitorenter
             7: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
            10: ldc           #13                 // String hello world
            12: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            15: aload_2
            16: monitorexit
            17: goto          25
            20: astore_3
            21: aload_2
            22: monitorexit
            23: aload_3
            24: athrow
            25: return
          Exception table:
             from    to  target type
                 7    17    20   any
                20    23    20   any
          LineNumberTable:
            line 26: 0
            line 27: 7
            line 28: 15
            line 29: 25
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      26     0  this   Lcom/example/jvm/bytecode/MyTest2;
                   0      26     1   str   Ljava/lang/String;
          StackMapTable: number_of_entries = 2
               frame_type = 255 /* full_frame */
              offset_delta = 20
              locals = [ class com/example/jvm/bytecode/MyTest2, class java/lang/String, class java/lang/Object ]
              stack = [ class java/lang/Throwable ]
               frame_type = 250 /* chop */
              offset_delta = 4
    

      出现了6: monitorenter和22: monitorexit

    给当前MyTest2类所对应的class对象上锁

    private synchronized static void test2(){

    }

    给当前对象上锁

    private synchronized void setX(int x){
    this.x = x;
    }

    五、字节码文件分析

    最终需要分析的java文件

    package com.example.jvm.bytecode;
    
    public class MyTest2 {
    
        String str = "Welcome";
    
        private  int x = 5;
    
        public static  Integer in = 10;
    
        public static void main(String[] args) {
            MyTest2 myTest2 = new MyTest2();
    
            myTest2.setX(8);
    
            in = 20;
        }
    
        private synchronized void setX(int x){
            this.x = x;
        }
    
        private void test(String str){
            synchronized (str){
                System.out.println("hello world");
            }
        }
    
        private synchronized static void test2(){
    
        }
      }
    

      然后反编译MyTest2.class

    Classfile /D:/workspace/study/ jvm_demo/build/classes/java/main/com/example/jvm/bytecode/MyTest2.class
      Last modified 2019-6-27; size 1265 bytes
      MD5 checksum 1ca3fedabb74af431cc850f3f87b7763
      Compiled from "MyTest2.java"
    public class com.example.jvm.bytecode.MyTest2
      SourceFile: "MyTest2.java"
      minor version: 0
      major version: 51
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #13.#45        //  java/lang/Object."<init>":()V
       #2 = String             #46            //  Welcome
       #3 = Fieldref           #5.#47         //  com/example/jvm/bytecode/MyTest2.str:Ljava/lang/String;
       #4 = Fieldref           #5.#48         //  com/example/jvm/bytecode/MyTest2.x:I
       #5 = Class              #49            //  com/example/jvm/bytecode/MyTest2
       #6 = Methodref          #5.#45         //  com/example/jvm/bytecode/MyTest2."<init>":()V
       #7 = Methodref          #5.#50         //  com/example/jvm/bytecode/MyTest2.setX:(I)V
       #8 = Methodref          #51.#52        //  java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       #9 = Fieldref           #5.#53         //  com/example/jvm/bytecode/MyTest2.in:Ljava/lang/Integer;
      #10 = Fieldref           #54.#55        //  java/lang/System.out:Ljava/io/PrintStream;
      #11 = String             #56            //  hello world
      #12 = Methodref          #57.#58        //  java/io/PrintStream.println:(Ljava/lang/String;)V
      #13 = Class              #59            //  java/lang/Object
      #14 = Utf8               str
      #15 = Utf8               Ljava/lang/String;
      #16 = Utf8               x
      #17 = Utf8               I
      #18 = Utf8               in
      #19 = Utf8               Ljava/lang/Integer;
      #20 = Utf8               <init>
      #21 = Utf8               ()V
      #22 = Utf8               Code
      #23 = Utf8               LineNumberTable
      #24 = Utf8               LocalVariableTable
      #25 = Utf8               this
      #26 = Utf8               Lcom/example/jvm/bytecode/MyTest2;
      #27 = Utf8               main
      #28 = Utf8               ([Ljava/lang/String;)V
      #29 = Utf8               args
      #30 = Utf8               [Ljava/lang/String;
      #31 = Utf8               myTest2
      #32 = Utf8               setX
      #33 = Utf8               (I)V
      #34 = Utf8               test
      #35 = Utf8               (Ljava/lang/String;)V
      #36 = Utf8               StackMapTable
      #37 = Class              #49            //  com/example/jvm/bytecode/MyTest2
      #38 = Class              #60            //  java/lang/String
      #39 = Class              #59            //  java/lang/Object
      #40 = Class              #61            //  java/lang/Throwable
      #41 = Utf8               test2
      #42 = Utf8               <clinit>
      #43 = Utf8               SourceFile
      #44 = Utf8               MyTest2.java
      #45 = NameAndType        #20:#21        //  "<init>":()V
      #46 = Utf8               Welcome
      #47 = NameAndType        #14:#15        //  str:Ljava/lang/String;
      #48 = NameAndType        #16:#17        //  x:I
      #49 = Utf8               com/example/jvm/bytecode/MyTest2
      #50 = NameAndType        #32:#33        //  setX:(I)V
      #51 = Class              #62            //  java/lang/Integer
      #52 = NameAndType        #63:#64        //  valueOf:(I)Ljava/lang/Integer;
      #53 = NameAndType        #18:#19        //  in:Ljava/lang/Integer;
      #54 = Class              #65            //  java/lang/System
      #55 = NameAndType        #66:#67        //  out:Ljava/io/PrintStream;
      #56 = Utf8               hello world
      #57 = Class              #68            //  java/io/PrintStream
      #58 = NameAndType        #69:#35        //  println:(Ljava/lang/String;)V
      #59 = Utf8               java/lang/Object
      #60 = Utf8               java/lang/String
      #61 = Utf8               java/lang/Throwable
      #62 = Utf8               java/lang/Integer
      #63 = Utf8               valueOf
      #64 = Utf8               (I)Ljava/lang/Integer;
      #65 = Utf8               java/lang/System
      #66 = Utf8               out
      #67 = Utf8               Ljava/io/PrintStream;
      #68 = Utf8               java/io/PrintStream
      #69 = Utf8               println
    {
      java.lang.String str;
        flags:
    
      private int x;
        flags: ACC_PRIVATE
    
      public static java.lang.Integer in;
        flags: ACC_PUBLIC, ACC_STATIC
    
      public com.example.jvm.bytecode.MyTest2();
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: aload_0
             5: ldc           #2                  // String Welcome
             7: putfield      #3                  // Field str:Ljava/lang/String;
            10: aload_0
            11: iconst_5
            12: putfield      #4                  // Field x:I
            15: return
          LineNumberTable:
            line 3: 0
            line 5: 4
            line 7: 10
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      16     0  this   Lcom/example/jvm/bytecode/MyTest2;
    
      public static void main(java.lang.String[]);
        flags: ACC_PUBLIC, ACC_STATIC
        Code:
          stack=2, locals=2, args_size=1
             0: new           #5                  // class com/example/jvm/bytecode/MyTest2
             3: dup
             4: invokespecial #6                  // Method "<init>":()V
             7: astore_1
             8: aload_1
             9: bipush        8
            11: invokespecial #7                  // Method setX:(I)V
            14: bipush        20
            16: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
            19: putstatic     #9                  // Field in:Ljava/lang/Integer;
            22: return
          LineNumberTable:
            line 12: 0
            line 14: 8
            line 16: 14
            line 17: 22
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      23     0  args   [Ljava/lang/String;
                   8      15     1 myTest2   Lcom/example/jvm/bytecode/MyTest2;
    
      private synchronized void setX(int);
        flags: ACC_PRIVATE, ACC_SYNCHRONIZED
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: iload_1
             2: putfield      #4                  // Field x:I
             5: return
          LineNumberTable:
            line 20: 0
            line 21: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0       6     0  this   Lcom/example/jvm/bytecode/MyTest2;
                   0       6     1     x   I
    
      private void test(java.lang.String);
        flags: ACC_PRIVATE
        Code:
          stack=2, locals=4, args_size=2
             0: aload_1
             1: dup
             2: astore_2
             3: monitorenter
             4: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
             7: ldc           #11                 // String hello world
             9: invokevirtual #12                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            12: aload_2
            13: monitorexit
            14: goto          22
            17: astore_3
            18: aload_2
            19: monitorexit
            20: aload_3
            21: athrow
            22: return
          Exception table:
             from    to  target type
                 4    14    17   any
                17    20    17   any
          LineNumberTable:
            line 24: 0
            line 25: 4
            line 26: 12
            line 27: 22
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      23     0  this   Lcom/example/jvm/bytecode/MyTest2;
                   0      23     1   str   Ljava/lang/String;
          StackMapTable: number_of_entries = 2
               frame_type = 255 /* full_frame */
              offset_delta = 17
              locals = [ class com/example/jvm/bytecode/MyTest2, class java/lang/String, class java/lang/Object ]
              stack = [ class java/lang/Throwable ]
               frame_type = 250 /* chop */
              offset_delta = 4
    
    
      private static synchronized void test2();
        flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNCHRONIZED
        Code:
          stack=0, locals=0, args_size=0
             0: return
          LineNumberTable:
            line 31: 0
    
      static {};
        flags: ACC_STATIC
        Code:
          stack=1, locals=0, args_size=0
             0: bipush        10
             2: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
             5: putstatic     #9                  // Field in:Ljava/lang/Integer;
             8: return
          LineNumberTable:
            line 9: 0
    }

    然后打开WinHex打开MyTest2.class 文件

  • 相关阅读:
    【poj1182】 食物链
    【bzoj1013】 JSOI2008—球形空间产生器sphere
    【codevs1200】 NOIP2012—同余方程
    【poj2891】 Strange Way to Express Integers
    【bzoj2819】 Nim
    【bzoj2463】 谁能赢呢?
    【poj3537】 Crosses ans Crosses
    【bzoj2115】 Xor
    下载时出现using cached如何解决
    如何设计一个"好的"测试用例?
  • 原文地址:https://www.cnblogs.com/linlf03/p/11097179.html
Copyright © 2020-2023  润新知