Java編譯與反編譯
導讀 | 我們可以透過javac 將Java程式的原始碼編譯成Java位元組碼,即我們常說的class檔案,這是我們通常意義上理解的編譯。 |
我們可以透過javac 將Java程式的原始碼編譯成Java位元組碼,即我們常說的class檔案,這是我們通常意義上理解的編譯。但是,位元組碼並不是機器語言,要想讓機器能夠執行,還需要把位元組碼翻譯成機器指令,這個過程是透過直譯器實現的,叫解釋執行。注意:大家別把編譯和解釋執行混淆了,而後面所說的後端編譯過程是JVM為提高效率做的最佳化,在不同的虛擬機器實現中,執行引擎在執行位元組碼的時候,通常會有解釋執行(透過直譯器執行)和編譯執行(透過即時編譯器產生原生程式碼執行)兩種選擇,也可能兩者兼備。所以大家可以思考下,Java到底是屬於編譯型語言還是直譯器語言呢?那為什麼java不直接編譯成可執行檔案呢,其實主要還是為了實現跨平臺。Java原始碼透過編譯成位元組碼,然後透過不同平臺的虛擬機器解釋執行,從而實現一次編譯,到處執行的跨平臺的效果。
Java語言的編譯期分為前端編譯和後端編譯兩個階段
前端編譯是指把*.java檔案轉變成*.class檔案的過程,包括詞法分析、語法分析、語義分析與中間程式碼生成。
主要有下面幾個步驟:
在部分商用虛擬機器中,Java程式最初是透過直譯器進行解釋執行的,當虛擬機器發現某個方法或程式碼塊的執行特別頻繁時,就會把這些程式碼認定為熱點程式碼
為了提高熱點程式碼的執行效率,在執行時, 虛擬機器將會把這些程式碼編譯成與本地平臺相關的機器碼
完成這個任務的後端編譯器稱為即時編譯器(JIT編譯器)
既然Java 編譯是指將 Java 原始碼編譯成 Java 位元組碼的過程
那麼Java 反編譯簡單說就是指根據 Java 位元組碼翻譯成原始碼的過程
首先這個原始碼是字元編碼,位元組碼是二進位制位元組流,並且原始碼是給人看的,位元組碼是給虛擬機器看的
因此如果想給人看,需要將位元組碼轉為原始碼。如果想給虛擬機器執行,需要將原始碼編譯成位元組碼,當我們有類檔案想看原始碼時,可以採用反編譯的方式實現
比如想了解某個Java 語法糖編譯後,再反編譯是什麼樣的;別人給你發一個 jar 包,你需要看其中某個類是怎麼寫的,等此類情況都可以考慮是用 Java 反編譯
GitHub :
官網:
下載後將類檔案或者 jar 包直接拖動到介面即可
下載地址:
官網:
可以使用 jad 命令將 JVM 中執行的 class 的 byte code 反編譯成 java 程式碼
javap是jdk自帶的一個工具,可以對程式碼反編譯,也可以檢視java編譯器生成的位元組碼
直接透過javap -help檢視其用法
用法: javap其中, 可能的選項包括: -help --help -? 輸出此用法訊息 -version 版本資訊 -v -verbose 輸出附加資訊 -l 輸出行號和本地變數表 -public 僅顯示公共類和成員 -protected 顯示受保護的/公共類和成員 -package 顯示程式包/受保護的/公共類 和成員 (預設) -p -private 顯示所有類和成員 -c 對程式碼進行反彙編 -s 輸出內部型別簽名 -sysinfo 顯示正在處理的類的 系統資訊 (路徑, 大小, 日期, MD5 雜湊) -constants 顯示最終常量 -classpath指定查詢使用者類檔案的位置 -cp指定查詢使用者類檔案的位置 -bootclasspath覆蓋引導類檔案的位置
基本使用:
javac Test.java javap -c Test.class
jclasslib 是一種視覺化的位元組碼檢視工具,可以直接在 IDEA 外掛安裝
安裝以後,在 IDEA 編譯原始碼後,可以選擇 View” ->“Show Bytecode With Jclasslib即可檢視位元組碼
可以直觀地看到 class 檔案包含基本資訊、常量池、介面資訊、欄位資訊、方法資訊和屬性資訊
其中方法資訊又包含行號表、區域性變數表,異常表等
要讀懂位元組碼指令涉及的知識很多,之後的文章會透過案例詳細講解class檔案結構和位元組碼指令的執行過程
推薦兩本非常經典的圖書:《深入理解 Java 虛擬機器》、《Java 虛擬機器規範》
下面看一個簡單和常見的案例:
public class ForEachDemo { public static void main(String[] args) { Listdata = new ArrayList<>(); data.add("a"); data.add("b"); for (String str : data) { System.out.println(str); } } }
我們直接在 IDEA 對該類檔案進行編譯,然後再 target 目錄中尋找該類,雙擊開啟,得到下面的反編譯原始碼:
public class ForEachDemo { public ForEachDemo() { } public static void main(String[] args) { Listdata = new ArrayList(); data.add("a"); data.add("b"); Iterator var2 = data.iterator(); while(var2.hasNext()) { String str = (String)var2.next(); System.out.println(str); } } }
從上述反編譯程式碼可以清楚地看到,原始程式碼中沒有編寫構造方法時,編譯器會自動生成一個預設構造方法;foreach 迴圈來遍歷 list 時,底層透過 iterator 來實現
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2764025/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java程式碼的編譯與反編譯那些事兒Java編譯
- java反編譯工具Java編譯
- Java反編譯器剖析Java編譯
- Java 反彙編、反編譯、volitale解讀Java編譯
- Android反編譯:反編譯工具和方法Android編譯
- [java]javap命令列反編譯Java命令列編譯
- 反編譯apk編譯APK
- JAVA反編譯技術研究心得Java編譯
- Android Apk反編譯系列教程(一)如何反編譯APKAndroidAPK編譯
- Java反編譯工具使用對比,最好用的Java反編譯工具 --- JD-GUI、XJadJava編譯GUI
- apk 包的破解與反編譯APK編譯
- 反編譯 iOS APP編譯iOSAPP
- android 反編譯Android編譯
- 如何保護Java程式 防止Java反編譯Java編譯
- Mac平臺反編譯Unity編譯的安卓apkMac編譯Unity安卓APK
- 7 款開源 Java 反編譯工具Java編譯
- 7款開源Java反編譯工具Java編譯
- 反編譯系列教程(上)編譯
- 反編譯系列教程(中)編譯
- Android 反編譯指南Android編譯
- Eclipse配置反編譯Eclipse編譯
- 小程式反編譯教程編譯
- .net反編譯工具ILSpy編譯
- 安卓反編譯詳解安卓編譯
- jive論壇反編譯編譯
- 反編譯技術探究編譯
- c#程式反編譯C#編譯
- gcc 編譯器與 clang 編譯器GC編譯
- Java Jar原始碼反編譯工具那家強JavaJAR原始碼編譯
- Android Apk反編譯得到Java原始碼AndroidAPK編譯Java原始碼
- 反編譯APK資原始檔與原始碼編譯APK原始碼
- 如何反編譯微信小程式?編譯微信小程式
- 安卓apk檔案反編譯安卓APK編譯
- [轉]andriod的apk檔案相關的編譯反編譯工具APK編譯
- Rust 交叉編譯與條件編譯總結Rust編譯
- 常見 APK 反編譯工具安裝與使用APK編譯
- JIT-動態編譯與AOT-靜態編譯:java/ java/ JavaScript/Dart亂談編譯JavaScriptDart
- ildasm、ilasm修改、反編譯 已經編譯的 dll檔案(c#)LDAASM編譯C#