Java反編譯工具,你知道幾個?
點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時間送達(dá)
編譯和反編譯
編程語言分成高級語言和低級語言。低級語言如機(jī)器語言、匯編語言。這類語言直接用計算機(jī)指令編寫命令,不需要編譯。這些語言機(jī)器能看到懂,但是程序員讀起來很費勁。而我們平時經(jīng)常用的語言C、Java、Python屬于高級語言,這些語言程序員能看的懂。而機(jī)器是看不懂的。
簡單的總結(jié)為:高級語言就是程序員認(rèn)識的語言,而低級語言是機(jī)器認(rèn)識的語言。而把高級語言轉(zhuǎn)成低級語言這個過程就是編譯,而反編譯就是把低級語言轉(zhuǎn)成高級語言。
有了反編譯,我們就可以看懂Java編譯器生成的字節(jié)碼,比如Synchronized的實現(xiàn)原理(監(jiān)聽器monitor)、枚舉、語法糖、泛型,這些都需要用到反編譯工具。
javap
javap是jdk自帶的反編譯命令,可以對代碼進(jìn)行反編譯,但是反編譯的并不是java文件。
使用格式
javap <options> <classes>
常用: javap -c 類名
-help --help -? 輸出此用法消息
-version 版本信息
-v -verbose 輸出附加信息
-l 輸出行號和本地變量表
-public 僅顯示公共類和成員
-protected 顯示受保護(hù)的/公共類和成員
-package 顯示程序包/受保護(hù)的/公共類和成員 (默認(rèn))
-p -private 顯示所有類和成員
-c 對代碼進(jìn)行反匯編
-s 輸出內(nèi)部類型簽名
-sysinfo 顯示正在處理的類的系統(tǒng)信息 (路徑, 大小, 日期, MD5 散列)
-constants 顯示最終常量
-classpath <path> 指定查找用戶類文件的位置
-cp <path> 指定查找用戶類文件的位置
-bootclasspath <path> 覆蓋引導(dǎo)類文件的位置
下面寫一段synchronized代碼:
public class SynchronizedTest {
private int count = 0;
public void addOne() {
synchronized (SynchronizedTest.class) {
count++;
}
}
}
執(zhí)行編譯和反編譯命令
javac SynchronizedTest .java
javap -c SynchronizedTest.class
直接用記事本打開SynchronizedTest.class文件是一堆亂碼文件,用sublime打開是一串?dāng)?shù)字
cafe babe 0000 0034 0017 0a00 0400 1209
0003 0013 0700 1407 0015 0100 0563 6f75
6e74 0100 0149 0100 063c 696e 6974 3e01
0003 2829 5601 0004 436f 6465 0100 0f4c
696e 654e 756d 6265 7254 6162 6c65 0100
0661 6464 4f6e 6501 000d 5374 6163 6b4d
6170 5461 626c 6507 0014 0700 1507 0016
反編譯后的代碼:
public class com.SynchronizedTest {
public com.SynchronizedTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_0
6: putfield #2 // Field count:I
9: return
public void addOne();
Code:
0: ldc #3 // class com/yyw/oil/web/admin/controller/purchase/SynchronizedTest
2: dup
3: astore_1
4: monitorenter
5: aload_0
6: dup
7: getfield #2 // Field count:I
10: iconst_1
11: iadd
12: putfield #2 // Field count:I
15: aload_1
16: monitorexit
17: goto 25
20: astore_2
21: aload_1
22: monitorexit
23: aload_2
24: athrow
25: return
Exception table:
from to target type
5 17 20 any
20 23 20 any
}
javap并沒有將字節(jié)碼反編譯成成java文件,而是生成一種另一種能看的懂得字節(jié)碼。可以看出被synchronized修飾的代碼包含 monitorenter 和 monitorexit。synchronized 底層依賴著兩個指令來實現(xiàn)同步, 這里看起來比較晦澀難懂。
CFR
在官網(wǎng)上下載jar,執(zhí)行如下命令:
java -jar cfr-0.151.jar SynchronizedTest.class
得到反編譯java文件:
public class SynchronizedTest {
private int count = 0;
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
public void addOne() {
Class<SynchronizedTest> clazz = SynchronizedTest.class;
synchronized (SynchronizedTest.class) {
++this.count;
// ** MonitorExit[var1_1] (shouldn't be in output)
return;
}
}
}
CFR還帶有一些參數(shù):
| 參數(shù) | 注釋 |
|---|---|
| --decodeenumswitch (boolean) | 去除switch對枚舉支持的語法糖 |
| --decodelambdas (boolean) | 去除lambda表達(dá)式的語法糖 |
| --decodestringswitch (boolean) | 去除switch string支持的語法糖 |
其余參數(shù)可使用如下命令查看:
java -jar cfr-0.151.jar --help
idea
使用idea生成class文件,用idea打開class文件即可。idea是絕大多數(shù)Java程序員使用的編輯器,使用idea打開文件比較方便、快捷。
作者 | jeremylai
來源 | cnblogs.com/jeremylai7/p/15136871.html

