摘要:反匯編器與反編譯器不同,反編譯器的目標是高級語言而非匯編語言。反匯編器的反匯編輸出通常格式化為適合人類閱讀,而非用作匯編器的輸入源,因此它主要是一個逆向工程工具。本文章參考了通過命令分析匯編指令反匯編器
問題描述
寫這篇文章是為了記錄我這幾天遇到的一個疑惑,并且順藤摸瓜的學習一下javap命令。遇到的疑惑是這樣的:我在看“使用枚舉類型實現(xiàn)單列模式”的博客時,發(fā)現(xiàn)一些博客中寫到的枚舉類型的反編譯結(jié)果包含的信息不盡相同:
??一些對枚舉類的反編譯結(jié)果僅僅包含像我們正常編寫的枚舉類的一些信息,如使用IDEA,Java Decompiler;
??而另一些反編譯結(jié)果則完全不同:一方面枚舉類成為了普通的class類,只是它繼承了Enum類,枚舉值都是public static final形式的對象;另一方面還多了static塊,values(),valueof()這些方法。
源代碼:
public enum Season { SPIRNG, SUMMER, AUTUMN, WINTER; public String allSeasons() { return SPIRNG.name() + " " + SUMMER.name() + " " + AUTUMN.name() +" " +WINTER.name(); } }
使用javap -c Season.class命令反編譯結(jié)果:
public final class Season extends java.lang.Enum{ public static final Season SPIRNG; public static final Season SUMMER; public static final Season AUTUMN; public static final Season WINTER; public static Season[] values(); Code: 0: getstatic #1 // Field $VALUES:[LSeason; 3: invokevirtual #2 // Method "[LSeason;".clone:()Ljava/lang/Object; 6: checkcast #3 // class "[LSeason;" 9: areturn public static Season valueOf(java.lang.String); Code: 0: ldc #4 // class Season 2: aload_0 3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; 6: checkcast #4 // class Season 9: areturn public java.lang.String allSeasons(); Code: 0: new #7 // class java/lang/StringBuilder 3: dup 4: invokespecial #8 // Method java/lang/StringBuilder." ":()V 7: getstatic #9 // Field SPIRNG:LSeason; 10: invokevirtual #10 // Method name:()Ljava/lang/String; 13: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 16: ldc #12 // String 18: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 21: getstatic #13 // Field SUMMER:LSeason; 24: invokevirtual #10 // Method name:()Ljava/lang/String; 27: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 30: ldc #12 // String 32: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 35: getstatic #14 // Field AUTUMN:LSeason; 38: invokevirtual #10 // Method name:()Ljava/lang/String; 41: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 44: ldc #12 // String 46: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 49: getstatic #15 // Field WINTER:LSeason; 52: invokevirtual #10 // Method name:()Ljava/lang/String; 55: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 58: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 61: areturn static {}; Code: 0: new #4 // class Season 3: dup 4: ldc #17 // String SPIRNG 6: iconst_0 7: invokespecial #18 // Method " ":(Ljava/lang/String;I)V 10: putstatic #9 // Field SPIRNG:LSeason; 13: new #4 // class Season 16: dup 17: ldc #19 // String SUMMER 19: iconst_1 20: invokespecial #18 // Method " ":(Ljava/lang/String;I)V 23: putstatic #13 // Field SUMMER:LSeason; 26: new #4 // class Season 29: dup 30: ldc #20 // String AUTUMN 32: iconst_2 33: invokespecial #18 // Method " ":(Ljava/lang/String;I)V 36: putstatic #14 // Field AUTUMN:LSeason; 39: new #4 // class Season 42: dup 43: ldc #21 // String WINTER 45: iconst_3 46: invokespecial #18 // Method " ":(Ljava/lang/String;I)V 49: putstatic #15 // Field WINTER:LSeason; 52: iconst_4 53: anewarray #4 // class Season 56: dup 57: iconst_0 58: getstatic #9 // Field SPIRNG:LSeason; 61: aastore 62: dup 63: iconst_1 64: getstatic #13 // Field SUMMER:LSeason; 67: aastore 68: dup 69: iconst_2 70: getstatic #14 // Field AUTUMN:LSeason; 73: aastore 74: dup 75: iconst_3 76: getstatic #15 // Field WINTER:LSeason; 79: aastore 80: putstatic #1 // Field $VALUES:[LSeason; 83: return }
使用Java Decompiler工具的反編譯結(jié)果:
public enum Season { SPIRNG, SUMMER, AUTUMN, WINTER; private Season() {} public String allSeasons() { return SPIRNG.name() + " " + SUMMER.name() + " " + AUTUMN.name() + " " + WINTER.name(); } }
從上面反編譯的結(jié)果我們總結(jié)差別如下
javap反編譯的結(jié)果中類的聲明不同,它是一個繼承了Enum類并且聲明為final類型的類;
javap反編譯結(jié)果中包含的方法不同,它包含了static(),valueOf(),values()方法;
javap反編譯結(jié)果中的方法體不同,它的方法體使用jvm指令來描述。
javap命令C:Usersw00457192>javap -h 用法: javap其中, 可能的選項包括: -? -h --help -help 輸出此幫助消息 -version 版本信息 -v -verbose 輸出附加信息 -l 輸出行號和本地變量表 -public 僅顯示公共類和成員 -protected 顯示受保護的/公共類和成員 -package 顯示程序包/受保護的/公共類和成員 (默認) -p -private 顯示所有類和成員 -c 對代碼進行反匯編 -s 輸出內(nèi)部類型簽名 -sysinfo 顯示正在處理的類的系統(tǒng)信息 (路徑, 大小, 日期, MD5 散列) -constants 顯示最終常量 --module <模塊>, -m <模塊> 指定包含要反匯編的類的模塊 --module-path <路徑> 指定查找應(yīng)用程序模塊的位置 --system 指定查找系統(tǒng)模塊的位置 --class-path <路徑> 指定查找用戶類文件的位置 -classpath <路徑> 指定查找用戶類文件的位置 -cp <路徑> 指定查找用戶類文件的位置 -bootclasspath <路徑> 覆蓋引導類文件的位置
從上面的信息我們可以看出javap -c是用于反匯編,而不是反編譯。參考維基百科的解釋如下:
反匯編器(disassembler)是一種將機器語言轉(zhuǎn)換為匯編語言的計算機程序——這與匯編器的目的相反。反匯編器與反編譯器不同,反編譯器的目標是高級語言而非匯編語言。反匯編器的反匯編輸出通常格式化為適合人類閱讀,而非用作匯編器的輸入源,因此它主要是一個逆向工程工具。結(jié)論
現(xiàn)在我們可以理解為什么javap和Java Decompiler的輸出中方法體有所不同了。
至于為什么Java Decompiler沒有包含static塊和values(),valueof()方法,我推測是因為反編譯器的目的是反編譯出源碼,而我們可以確定的是static塊和values()和valueof()這兩個方法是編譯器自己實現(xiàn)的,不是我們?nèi)藶樘砑拥模栽诜淳幾g器看來這不屬于源碼的一部分,因此沒有在編譯的結(jié)果中包含這些方法。
本文章參考了
??通過javap命令分析java匯編指令
??反匯編器
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/77697.html
摘要:提供給了用戶大量的語法糖,比如泛型自動裝箱拆箱循環(huán)變長參數(shù)內(nèi)部類枚舉類斷言新特性方法引用等解語法糖語法糖的存在主要是方便開發(fā)人員使用。 首先,部分總結(jié)文字引用 簡書作者:Eric新之助 。鏈接:https://www.jianshu.com/p/4de08deb6ba4 已獲得授權(quán) showImg(https://segmentfault.com/img/bVbfuX9?w=646&...
摘要:結(jié)構(gòu)型模式適配器模式橋接模式裝飾模式組合模式外觀模式享元模式代理模式。行為型模式模版方法模式命令模式迭代器模式觀察者模式中介者模式備忘錄模式解釋器模式模式狀態(tài)模式策略模式職責鏈模式責任鏈模式訪問者模式。 主要版本 更新時間 備注 v1.0 2015-08-01 首次發(fā)布 v1.1 2018-03-12 增加新技術(shù)知識、完善知識體系 v2.0 2019-02-19 結(jié)構(gòu)...
摘要:原文如果覺得我的文章對你有用,請隨意贊賞本文整理運行時獲取方法參數(shù)名的兩種方法,的最新的方法和之前的方法。文件中的調(diào)試信息上文介紹了通過新增的反射運行時獲取方法參數(shù)名。 原文:http://nullwy.me/2017/04/java...如果覺得我的文章對你有用,請隨意贊賞 本文整理 Java 運行時獲取方法參數(shù)名的兩種方法,Java 8 的最新的方法和 Java 8 之前的方法。 ...
摘要:導讀閱讀本文需要有足夠的時間,筆者會由淺到深帶你一步一步了解一個資深架構(gòu)師所要掌握的各類知識點,你也可以按照文章中所列的知識體系對比自身,對自己進行查漏補缺,覺得本文對你有幫助的話,可以點贊關(guān)注一下。目錄一基礎(chǔ)篇二進階篇三高級篇四架構(gòu)篇五擴 導讀:閱讀本文需要有足夠的時間,筆者會由淺到深帶你一步一步了解一個資深架構(gòu)師所要掌握的各類知識點,你也可以按照文章中所列的知識體系對比自身,對自己...
摘要:從字節(jié)碼的分析可以觀察到一個有趣的現(xiàn)象,再次看看我們的語句。這張表里每行的后面的數(shù)字代表源代碼的序號,冒號后面的數(shù)字代表字節(jié)碼里每行指令的序號。維護了源代碼同字節(jié)指令的映射關(guān)系,確保了代碼調(diào)試的順利進行。 javap是JDK自帶的工具: showImg(https://segmentfault.com/img/remote/1460000016730237); 這篇文章使用下面這段簡單...
閱讀 1478·2021-10-14 09:43
閱讀 1442·2021-10-09 09:58
閱讀 1937·2021-09-28 09:42
閱讀 3727·2021-09-26 09:55
閱讀 1752·2021-08-27 16:23
閱讀 2755·2021-08-23 09:46
閱讀 906·2019-08-30 15:55
閱讀 1405·2019-08-30 15:54