<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java編譯和反編譯那些事

          共 3354字,需瀏覽 7分鐘

           ·

          2021-10-26 01:22

          每個人都注定要體驗生命的美好,也要體驗其不可避免的暗黑之處:幻滅、衰老、疾病、孤獨、喪失、無意義、痛苦的選擇和死亡

          前言

          挺久沒更文章了,之前有一個月在面試,后來寫了篇面經(jīng),有一些朋友找我交流問題,所以一直沒時間寫技術(shù)文章,估計以后更新文章頻率不會那么高了,不過還是會定期分享的,我的目的還是希望我的每篇文章大家都能學(xué)到點東西

          基本概念

          我們可以通過javac命令將Java程序的源代碼編譯成Java字節(jié)碼,即我們常說的class文件,這是我們通常意義上理解的編譯

          但是,字節(jié)碼并不是機器語言,要想讓機器能夠執(zhí)行,還需要把字節(jié)碼翻譯成機器指令,這個過程是通過解釋器實現(xiàn)的,叫解釋執(zhí)行

          注意:大家別把編譯和解釋執(zhí)行混淆了,而后面所說的后端編譯過程是JVM為提高效率做的優(yōu)化

          在不同的虛擬機實現(xiàn)中,執(zhí)行引擎在執(zhí)行字節(jié)碼的時候,通常會有解釋執(zhí)行(通過解釋器執(zhí)行)和編譯執(zhí)行(通過即時編譯器產(chǎn)生本地代碼執(zhí)行)兩種選擇,也可能兩者兼?zhèn)?/p>

          所以大家可以思考下,Java到底是屬于編譯型語言還是解釋器語言呢

          那為什么java不直接編譯成可執(zhí)行文件呢

          為了實現(xiàn)跨平臺

          Java源碼通過編譯成字節(jié)碼,然后通過不同平臺的虛擬機解釋執(zhí)行,從而實現(xiàn) 一次編譯,到處運行的跨平臺的效果

          編譯原理

          Java語言的編譯期分為前端編譯和后端編譯兩個階段

          前端編譯

          前端編譯是指把*.java文件轉(zhuǎn)變成*.class文件的過程

          包括詞法分析、語法分析、語義分析與中間代碼生成

          主要有下面幾個步驟:

          后端編譯

          在部分商用虛擬機中,Java程序最初是通過解釋器進行解釋執(zhí)行的,當(dāng)虛擬機發(fā)現(xiàn)某個方法或代碼塊的運行特別頻繁時,就會把這些代碼認(rèn)定為熱點代碼

          為了提高熱點代碼的執(zhí)行效率,在運行時, 虛擬機將會把這些代碼編譯成與本地平臺相關(guān)的機器碼

          完成這個任務(wù)的后端編譯器稱為即時編譯器(JIT編譯器)

          反編譯

          什么是反編譯

          既然Java 編譯是指將 Java 源碼編譯成 Java 字節(jié)碼的過程

          那么Java 反編譯簡單說就是指根據(jù) Java 字節(jié)碼翻譯成源碼的過程

          為什么要有反編譯

          首先這個源碼是字符編碼,字節(jié)碼是二進制字節(jié)流,并且源碼是給人看的,字節(jié)碼是給虛擬機看的

          因此如果想給人看,需要將字節(jié)碼轉(zhuǎn)為源碼。如果想給虛擬機執(zhí)行,需要將源碼編譯成字節(jié)碼,當(dāng)我們有類文件想看源碼時,可以采用反編譯的方式實現(xiàn)

          比如想了解某個 Java 語法糖編譯后,再反編譯是什么樣的;別人給你發(fā)一個 jar 包,你需要看其中某個類是怎么寫的,等此類情況都可以考慮是用 Java 反編譯

          反編譯工具

          在線反編譯工具

          1.http://www.decompiler.com/

          2.http://www.javadecompilers.com/,該網(wǎng)站的主要優(yōu)勢在于有多種反編譯器可供選擇

          離線反編譯工具

          JD-GUI

          GitHub :https://github.com/java-decompiler/jd-gui

          官網(wǎng):http://java-decompiler.github.io/

          下載后將類文件或者 jar 包直接拖動到界面即可

          Luyten

          下載地址:https://github.com/deathmarine/Luyten/releases

          Arthas

          官網(wǎng):https://arthas.aliyun.com/doc/

          可以使用 jad 命令將 JVM 中運行的 class 的 byte code 反編譯成 java 代碼

          這個工具很好用,強烈推薦

          其他工具

          javap

          javap是jdk自帶的一個工具,可以對代碼反編譯,也可以查看java編譯器生成的字節(jié)碼

          直接通過javap -help查看其用法

          用法:?javap??
          其中,?可能的選項包括:
          ??-help??--help??-?????????輸出此用法消息
          ??-version?????????????????版本信息
          ??-v??-verbose?????????????輸出附加信息
          ??-l???????????????????????輸出行號和本地變量表
          ??-public??????????????????僅顯示公共類和成員
          ??-protected???????????????顯示受保護的/公共類和成員
          ??-package?????????????????顯示程序包/受保護的/公共類
          ???????????????????????????和成員?(默認(rèn))
          ??-p??-private?????????????顯示所有類和成員
          ??-c???????????????????????對代碼進行反匯編
          ??-s???????????????????????輸出內(nèi)部類型簽名
          ??-sysinfo?????????????????顯示正在處理的類的
          ???????????????????????????系統(tǒng)信息?(路徑,?大小,?日期,?MD5?散列)
          ??-constants???????????????顯示最終常量
          ??-classpath?????????指定查找用戶類文件的位置
          ??-cp????????????????指定查找用戶類文件的位置
          ??-bootclasspath?????覆蓋引導(dǎo)類文件的位置

          基本使用:

          javac?Test.java
          javap?-c?Test.class

          jclasslib

          jclasslib 是一種可視化的字節(jié)碼查看工具,可以直接在 IDEA 插件安裝

          安裝以后,在 IDEA 編譯源碼后,可以選擇 View” ->“Show Bytecode With Jclasslib即可查看字節(jié)碼

          可以直觀地看到 class 文件包含基本信息、常量池、接口信息、字段信息、方法信息和屬性信息

          其中方法信息又包含行號表、局部變量表,異常表等

          要讀懂字節(jié)碼指令涉及的知識很多,之后的文章會通過案例詳細(xì)講解class文件結(jié)構(gòu)和字節(jié)碼指令的執(zhí)行過程

          推薦兩本非常經(jīng)典的圖書:《深入理解 Java 虛擬機》、《Java 虛擬機規(guī)范》

          大家也可以通過 Oracle 的 Java 標(biāo)準(zhǔn) 網(wǎng)頁里瀏覽和下載《Java 語言規(guī)范》、《Java 虛擬機規(guī)范》

          反編譯示例

          下面看一個簡單和常見的案例:

          public?class?ForEachDemo?{
          ????public?static?void?main(String[]?args)?{

          ????????List?data?=?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)?{
          ????????List?data?=?new?ArrayList();
          ????????data.add("a");
          ????????data.add("b");
          ????????Iterator?var2?=?data.iterator();

          ????????while(var2.hasNext())?{
          ????????????String?str?=?(String)var2.next();
          ????????????System.out.println(str);
          ????????}

          ????}
          }

          從上述反編譯代碼可以清楚地看到,原始代碼中沒有編寫構(gòu)造方法時,編譯器會自動生成一個默認(rèn)構(gòu)造方法;foreach 循環(huán)來遍歷 list 時,底層通過 iterator 來實現(xiàn)

          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费大黄网站 | 一级片直播 | 六月婷婷色 | 日本精品一区二区视频 | 无码人妻一区二区蜜桃 |