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 反彙編、反編譯、volitale解讀Java編譯
- android 反編譯Android編譯
- Android Apk反編譯系列教程(一)如何反編譯APKAndroidAPK編譯
- Eclipse配置反編譯Eclipse編譯
- Android 反編譯指南Android編譯
- c#程式反編譯C#編譯
- 反編譯系列教程(上)編譯
- 反編譯系列教程(中)編譯
- 小程式反編譯教程編譯
- Java Jar原始碼反編譯工具那家強JavaJAR原始碼編譯
- 反編譯之安裝Apktool編譯APK
- Rust 交叉編譯與條件編譯總結Rust編譯
- JIT-動態編譯與AOT-靜態編譯:java/ java/ JavaScript/Dart亂談編譯JavaScriptDart
- 使用ilasm 和 ildasm編譯和反編譯工具對DLL檔案修改ASMLDA編譯
- Java動態編譯優化——提升編譯速度(N倍)Java編譯優化
- android 反編譯APK取原始碼。Android編譯APK原始碼
- 使用AndroidKiller進行APK反編譯AndroidAPK編譯
- 如何反編譯微信小程式?編譯微信小程式
- jad反編譯常用命令編譯
- python反編譯之位元組碼Python編譯
- Android反編譯工具Apktool淺析Android編譯APK
- 使用Reflector和Filedisassembler逆向編譯反編譯.cs.dll檔案程式碼編譯
- mac上Apk反編譯工具合集整理與資源MacAPK編譯
- IDEA報錯java: 編譯失敗: 內部 java 編譯器錯誤IdeaJava編譯
- N1064編譯鏈編譯編譯
- libusb android ndk編譯--編譯mipsAndroid編譯
- hadoop編譯—+2.x編譯Hadoop編譯
- java反編譯luyten使用,以及中文亂碼,如何解決Java編譯
- 編譯編譯
- .NET反編譯神器ILSpy怎麼用?編譯
- Cython加密python程式碼防止反編譯加密Python編譯
- .NET應用如何防止被反編譯編譯
- 微信小程式反編譯~2020年微信小程式編譯
- 有償找一懂dylib反編譯編譯
- Android的反編譯(佈局植入篇)Android編譯
- ecplise配置jad反編譯.class檔案編譯