java中的反编译使用的命令
Java开发中偶尔会有使用把编译后的Java文件反编译一下
1.先写一个Java类 Test0
package com.线程.多线程核心技术._2;
public class Test0 {
synchronized public static void testMethod() {
}
public static void main(String[] args) {
}
}
2.使用命令javac Test0.java
,会得到一个文件Test0.class
3.接下反编译。使用命令javap -c -v Test0.class
4.查询反编译的结果
Classfile /Users/liyiruo/IdeaProjects/study/src/main/java/com/线程/多线程核心技术/_2/Test0.class
Last modified 2020-10-9; size 343 bytes
MD5 checksum c16e6ceada756dd4c2f32daa3747516d
Compiled from "Test0.java"
public class com.线程.多线程核心技术._2.Test0
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#13 // java/lang/Object."<init>":()V
#2 = Class #14 // com/线程/多线程核心技术/_2/Test0
#3 = Class #15 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 testMethod
#9 = Utf8 main
#10 = Utf8 ([Ljava/lang/String;)V
#11 = Utf8 SourceFile
#12 = Utf8 Test0.java
#13 = NameAndType #4:#5 // "<init>":()V
#14 = Utf8 com/线程/多线程核心技术/_2/Test0
#15 = Utf8 java/lang/Object
{
public com.线程.多线程核心技术._2.Test0();
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 static synchronized void testMethod();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=0, locals=0, args_size=0
0: return
LineNumberTable:
line 5: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 9: 0
}
SourceFile: "Test0.java"
5.解读反编译后的内容
synchronized public static void testMethod() { }
这个方法的flags
是flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
指的是访问权限为:public,static,synchronized
6.其他 synchronized 修饰方法和修饰代码块的区别
package com.线程.多线程核心技术._2;
public class Test1 {
public void myMethod() {
synchronized (this) {
int age = 100;
}
}
public static void main(String[] args) {
Test1 test = new Test1();
test.myMethod();
}
}
反编译后结果为:
Classfile /Users/liyiruo/IdeaProjects/study/src/main/java/com/线程/多线程核心技术/_2/Test1.class
Last modified 2020-10-9; size 495 bytes
MD5 checksum 9ddb52e82ff02785d9947879aed55dcb
Compiled from "Test1.java"
public class com.线程.多线程核心技术._2.Test1
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #5.#19 // java/lang/Object."<init>":()V
#2 = Class #20 // com/线程/多线程核心技术/_2/Test1
#3 = Methodref #2.#19 // com/线程/多线程核心技术/_2/Test1."<init>":()V
#4 = Methodref #2.#21 // com/线程/多线程核心技术/_2/Test1.myMethod:()V
#5 = Class #22 // java/lang/Object
#6 = Utf8 <init>
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 myMethod
#11 = Utf8 StackMapTable
#12 = Class #20 // com/线程/多线程核心技术/_2/Test1
#13 = Class #22 // java/lang/Object
#14 = Class #23 // java/lang/Throwable
#15 = Utf8 main
#16 = Utf8 ([Ljava/lang/String;)V
#17 = Utf8 SourceFile
#18 = Utf8 Test1.java
#19 = NameAndType #6:#7 // "<init>":()V
#20 = Utf8 com/线程/多线程核心技术/_2/Test1
#21 = NameAndType #10:#7 // myMethod:()V
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/Throwable
{
public com.线程.多线程核心技术._2.Test1();
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 9: 0
public void myMethod();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: bipush 100
6: istore_2
7: aload_1
8: monitorexit
9: goto 17
12: astore_3
13: aload_1
14: monitorexit
15: aload_3
16: athrow
17: return
Exception table:
from to target type
4 9 12 any
12 15 12 any
LineNumberTable:
line 11: 0
line 12: 4
line 13: 7
line 14: 17
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 12
locals = [ class com/线程/多线程核心技术/_2/Test1, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class com/线程/多线程核心技术/_2/Test1
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method myMethod:()V
12: return
LineNumberTable:
line 17: 0
line 18: 8
line 19: 12
}
SourceFile: "Test1.java"
7.重点 字节码中使用了monitorenter和monitorexit
public void myMethod();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: bipush 100
6: istore_2
7: aload_1
8: monitorexit
9: goto 17
12: astore_3
13: aload_1
14: monitorexit
15: aload_3
16: athrow
17: return
8.总结:
synchronized 修饰方法 方法的flags上有acc_synchronized
synchronized 修饰代码块 字节码中使用了monitorenter 和 monitorexit