<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編譯和反編譯那些事

          共 6067字,需瀏覽 13分鐘

           ·

          2021-03-17 22:23



          基本概念

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

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

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

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

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

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

          為了實(shí)現(xiàn)跨平臺(tái)

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

          編譯原理

          Java語(yǔ)言的編譯期分為前端編譯和后端編譯兩個(gè)階段

          前端編譯

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

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

          主要有下面幾個(gè)步驟:

          后端編譯

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

          為了提高熱點(diǎn)代碼的執(zhí)行效率,在運(yùn)行時(shí), 虛擬機(jī)將會(huì)把這些代碼編譯成與本地平臺(tái)相關(guān)的機(jī)器碼

          完成這個(gè)任務(wù)的后端編譯器稱(chēng)為即時(shí)編譯器(JIT編譯器)

          之前寫(xiě)過(guò)一篇文章詳細(xì)講這個(gè):聊聊JIT是如何影響JVM性能的

          反編譯

          什么是反編譯

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

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

          為什么要有反編譯

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

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

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

          反編譯工具

          在線反編譯工具

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

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

          離線反編譯工具

          JD-GUI

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

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

          下載后將類(lèi)文件或者 jar 包直接拖動(dòng)到界面即可

          Luyten

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

          Arthas

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

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

          這個(gè)工具很好用,強(qiáng)烈推薦

          其他工具

          javap

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

          直接通過(guò)javap -help查看其用法

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

          基本使用:

          javac Test.java
          javap -c Test.class

          jclasslib

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

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

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

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

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

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

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

          我公眾號(hào)后臺(tái)回復(fù)"666"也可獲取pdf版電子書(shū)籍

          反編譯示例

          下面看一個(gè)簡(jiǎn)單和常見(jiàn)的案例:

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

                  List<String> data = new ArrayList<>();
                  data.add("a");
                  data.add("b");

                  for (String str : data) {
                      System.out.println(str);
                  }

              }
          }

          我們直接在 IDEA 對(duì)該類(lèi)文件進(jìn)行編譯,然后再 target 目錄中尋找該類(lèi),雙擊打開(kāi),得到下面的反編譯源碼:

          public class ForEachDemo {
              public ForEachDemo() {
              }

              public static void main(String[] args) {
                  List<String> 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);
                  }

              }
          }

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


          還有年味的文章,F(xiàn)orkJoinPool 大型圖文現(xiàn)場(chǎng)

          2021-02-18

          啥是 PR?啥又是MR?

          2021-02-22

          位運(yùn)算就能做到,就不要寫(xiě)那么多代碼了【位運(yùn)算奇淫技巧】

          2021-02-22



          瀏覽 56
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  天堂无码av | 国产毛片毛片毛片 | 免费在线观看网站性情淫乱做爱 | 免费看一级黄色片 | 国产精品777 |