假设要对下面代码进行反汇编:
package org.example.volatiletest;
public class VolatileTest {
public static volatile boolean stop = false;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
int i = 0;
while (!stop){
i++;
}
});
t.start();
System.out.println("start thread.");
Thread.sleep(1000);
stop = true;
}
}
需要将编译好的 插件hsdis-amd64.lib hsdis-amd64.dll放到 C:\Program Files\Java\jdk1.8.0_181\jre\bin\server 路径下(实际路径根据自己安装路径修改)
然后在idea中配置jvm参数: VolatileTest 是要反汇编的类的名字(如果要反汇编具体的某个方法,类名后面加上.方法名) 并且需要指定安装了插件的jre的路径,如下图所示:
-server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*VolatileTest.*
注意是Java\jdk1.8.0_181\jre\bin\server 路径,而不是 C:\Program Files\Java\jre1.8.0_181\bin\server, 我就是因为路径配置错了,一直报下面这样的错误提示:
接下来,运行代码,就可以得到代码对应的汇编语言的代码了,这里只挑出来最关键的一部分,加了volatile关键字后,汇编代码中会在stop变量上加上一个lock指令:
javap -v 反编译后如下:
Classfile /E:/Baidudownload/JUC/out/production/JUC/org/example/volatiletest/VolatileTest.class
Last modified 2021-8-14; size 1546 bytes
MD5 checksum 15f06b76e561d96fbaa0b940f4685186
Compiled from "VolatileTest.java"
public class org.example.volatiletest.VolatileTest
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #14.#39 // java/lang/Object."<init>":()V
#2 = Class #40 // java/lang/Thread
#3 = InvokeDynamic #0:#45 // #0:run:()Ljava/lang/Runnable;
#4 = Methodref #2.#46 // java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
#5 = Methodref #2.#47 // java/lang/Thread.start:()V
#6 = Fieldref #48.#49 // java/lang/System.out:Ljava/io/PrintStream;
#7 = String #50 // start thread.
#8 = Methodref #51.#52 // java/io/PrintStream.println:(Ljava/lang/String;)V
#9 = Long 1000l
#11 = Methodref #2.#53 // java/lang/Thread.sleep:(J)V
#12 = Fieldref #13.#54 // org/example/volatiletest/VolatileTest.stop:Z
#13 = Class #55 // org/example/volatiletest/VolatileTest
#14 = Class #56 // java/lang/Object
#15 = Utf8 stop
#16 = Utf8 Z
#17 = Utf8 <init>
#18 = Utf8 ()V
#19 = Utf8 Code
#20 = Utf8 LineNumberTable
#21 = Utf8 LocalVariableTable
#22 = Utf8 this
#23 = Utf8 Lorg/example/volatiletest/VolatileTest;
#24 = Utf8 main
#25 = Utf8 ([Ljava/lang/String;)V
#26 = Utf8 args
#27 = Utf8 [Ljava/lang/String;
#28 = Utf8 t
#29 = Utf8 Ljava/lang/Thread;
#30 = Utf8 Exceptions
#31 = Class #57 // java/lang/InterruptedException
#32 = Utf8 lambda$main$0
#33 = Utf8 i
#34 = Utf8 I
#35 = Utf8 StackMapTable
#36 = Utf8 <clinit>
#37 = Utf8 SourceFile
#38 = Utf8 VolatileTest.java
#39 = NameAndType #17:#18 // "<init>":()V
#40 = Utf8 java/lang/Thread
#41 = Utf8 BootstrapMethods
#42 = MethodHandle #6:#58 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#43 = MethodType #18 // ()V
#44 = MethodHandle #6:#59 // invokestatic org/example/volatiletest/VolatileTest.lambda$main$0:()V
#45 = NameAndType #60:#61 // run:()Ljava/lang/Runnable;
#46 = NameAndType #17:#62 // "<init>":(Ljava/lang/Runnable;)V
#47 = NameAndType #63:#18 // start:()V
#48 = Class #64 // java/lang/System
#49 = NameAndType #65:#66 // out:Ljava/io/PrintStream;
#50 = Utf8 start thread.
#51 = Class #67 // java/io/PrintStream
#52 = NameAndType #68:#69 // println:(Ljava/lang/String;)V
#53 = NameAndType #70:#71 // sleep:(J)V
#54 = NameAndType #15:#16 // stop:Z
#55 = Utf8 org/example/volatiletest/VolatileTest
#56 = Utf8 java/lang/Object
#57 = Utf8 java/lang/InterruptedException
#58 = Methodref #72.#73 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#59 = Methodref #13.#74 // org/example/volatiletest/VolatileTest.lambda$main$0:()V
#60 = Utf8 run
#61 = Utf8 ()Ljava/lang/Runnable;
#62 = Utf8 (Ljava/lang/Runnable;)V
#63 = Utf8 start
#64 = Utf8 java/lang/System
#65 = Utf8 out
#66 = Utf8 Ljava/io/PrintStream;
#67 = Utf8 java/io/PrintStream
#68 = Utf8 println
#69 = Utf8 (Ljava/lang/String;)V
#70 = Utf8 sleep
#71 = Utf8 (J)V
#72 = Class #75 // java/lang/invoke/LambdaMetafactory
#73 = NameAndType #76:#80 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#74 = NameAndType #32:#18 // lambda$main$0:()V
#75 = Utf8 java/lang/invoke/LambdaMetafactory
#76 = Utf8 metafactory
#77 = Class #82 // java/lang/invoke/MethodHandles$Lookup
#78 = Utf8 Lookup
#79 = Utf8 InnerClasses
#80 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#81 = Class #83 // java/lang/invoke/MethodHandles
#82 = Utf8 java/lang/invoke/MethodHandles$Lookup
#83 = Utf8 java/lang/invoke/MethodHandles
{
public static volatile boolean stop;
descriptor: Z
flags: ACC_PUBLIC, ACC_STATIC, ACC_VOLATILE
public org.example.volatiletest.VolatileTest();
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
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lorg/example/volatiletest/VolatileTest;
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: new #2 // class java/lang/Thread
3: dup
4: invokedynamic #3, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
9: invokespecial #4 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
12: astore_1
13: aload_1
14: invokevirtual #5 // Method java/lang/Thread.start:()V
17: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
20: ldc #7 // String start thread.
22: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: ldc2_w #9 // long 1000l
28: invokestatic #11 // Method java/lang/Thread.sleep:(J)V
31: iconst_1
32: putstatic #12 // Field stop:Z
35: return
LineNumberTable:
line 6: 0
line 12: 13
line 13: 17
line 14: 25
line 15: 31
line 16: 35
LocalVariableTable:
Start Length Slot Name Signature
0 36 0 args [Ljava/lang/String;
13 23 1 t Ljava/lang/Thread;
Exceptions:
throws java.lang.InterruptedException
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_0
1: putstatic #12 // Field stop:Z
4: return
LineNumberTable:
line 4: 0
}
SourceFile: "VolatileTest.java"
InnerClasses:
public static final #78= #77 of #81; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #42 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#43 ()V
#44 invokestatic org/example/volatiletest/VolatileTest.lambda$main$0:()V
#43 ()V