Java 虛擬機器之六:javap工具
一:簡介
javap是JDK自帶的反彙編器,可以檢視java編譯器為我們生成的位元組碼。透過它,我們可以對照原始碼和位元組碼,從而瞭解很多編譯器內部的工作。
javap命令的常用引數有:
-l 列印行和本地變數表
-public 只顯示公共類和成員變數
-protected 只顯示公共的、受保護的類和變數
-private 顯示所有的類和成員變數
-p 顯示所有的類和成員變數
-Joption 給jvm指定引數,例如:
javap -J-version
javap -J-Djava.security.manager -J-Djava.security.policy=MyPolicy
-s 列印內部型別簽名(用於泛型)
-sysinfo 列印被處理類的系統資訊(路徑,大小,日誌,MD5雜湊)
-constants 顯示static final常量
-c 輸出分解後的程式碼。例如,類中每一個方法內,包含java位元組碼的指令
-verbose 輸出棧大小,變數(locals)和方法引數的個數
-classpath path 指定查詢類的路徑.如果設定該值,則會覆蓋預設值和CLASSPATH環境變數。
-bootclasspath path 指定啟動類的路徑,預設值是jre/lib/rt.jar 和 其他少數的jar.
-extdir dirs 覆蓋 java.ext.dirs路徑
二:例項
1.Java原始碼
public class Demo { private String name = "張三"; public static void main(String args[]) { System.out.println("Hello World."); } private void sayHello() { System.out.println("Hello " + name); } }
2.javac編譯後的位元組碼
CA FE BA BE 00 00 00 34 00 36 0A 00 0D 00 1E 08 00 1F 09 00 0C 00 20 09 00 21 00 22 08 00 23 0A 00 24 00 25 07 00 26 0A 00 07 00 1E 08 00 27 0A 00 07 00 28 0A 00 07 00 29 07 00 2A 07 00 2B 01 00 04 6E 61 6D 65 01 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 01 00 12 4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 00 04 74 68 69 73 01 00 28 4C 63 6F 6D 2F 62 72 69 6C 6C 69 61 6E 74 73 74 61 72 2F 63 69 6D 63 2F 69 6D 2F 64 65 73 6B 74 6F 70 2F 44 65 6D 6F 3B 01 00 04 6D 61 69 6E 01 00 16 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00 04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 08 73 61 79 48 65 6C 6C 6F 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 01 00 09 44 65 6D 6F 2E 6A 61 76 61 0C 00 10 00 11 01 00 06 E5 BC A0 E4 B8 89 0C 00 0E 00 0F 07 00 2C 0C 00 2D 00 2E 01 00 0C 48 65 6C 6C 6F 20 57 6F 72 6C 64 2E 07 00 2F 0C 00 30 00 31 01 00 17 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 42 75 69 6C 64 65 72 01 00 06 48 65 6C 6C 6F 20 0C 00 32 00 33 0C 00 34 00 35 01 00 26 63 6F 6D 2F 62 72 69 6C 6C 69 61 6E 74 73 74 61 72 2F 63 69 6D 63 2F 69 6D 2F 64 65 73 6B 74 6F 70 2F 44 65 6D 6F 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01 00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07 70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00 06 61 70 70 65 6E 64 01 00 2D 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 42 75 69 6C 64 65 72 3B 01 00 08 74 6F 53 74 72 69 6E 67 01 00 14 28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 00 21 00 0C 00 0D 00 00 00 01 00 02 00 0E 00 0F 00 00 00 03 00 01 00 10 00 11 00 01 00 12 00 00 00 39 00 02 00 01 00 00 00 0B 2A B7 00 01 2A 12 02 B5 00 03 B1 00 00 00 02 00 13 00 00 00 0A 00 02 00 00 00 13 00 04 00 14 00 14 00 00 00 0C 00 01 00 00 00 0B 00 15 00 16 00 00 00 09 00 17 00 18 00 01 00 12 00 00 00 37 00 02 00 01 00 00 00 09 B2 00 04 12 05 B6 00 06 B1 00 00 00 02 00 13 00 00 00 0A 00 02 00 00 00 17 00 08 00 18 00 14 00 00 00 0C 00 01 00 00 00 09 00 19 00 1A 00 00 00 02 00 1B 00 11 00 01 00 12 00 00 00 4B 00 03 00 01 00 00 00 1D B2 00 04 BB 00 07 59 B7 00 08 12 09 B6 00 0A 2A B4 00 03 B6 00 0A B6 00 0B B6 00 06 B1 00 00 00 02 00 13 00 00 00 0A 00 02 00 00 00 1B 00 1C 00 1C 00 14 00 00 00 0C 00 01 00 00 00 1D 00 15 00 16 00 00 00 01 00 1C 00 00 00 02 00 1D
3.javap返彙編後的內容
javap -p -v Demo
預設情況下javap會列印所有非私有的欄位和方法,當加了-p選項後,它還將列印私有的欄位和方法;-v 它儘可能地列印所有資訊。如果只需要查詢方法對應的位元組碼,那麼可以用-c代替-v.
=================基本資訊(涵蓋了原class檔案的相關資訊)======================= Classfile /D:/workspace/donkey/cimc-im-desktop/target/classes/com/brilliantstar/cimc/im/desktop/Demo.class Last modified 2018-9-6; size 909 bytes MD5 checksum 0f9cd841c4a2ab1f6a00163e55ca6e0f Compiled from "Demo.java" public class com.brilliantstar.cimc.im.desktop.Demo minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER =================常量池(用來存放各種常量及符號引用)======================= Constant pool: #1 = Methodref #13.#30 // java/lang/Object."<init>":()V #2 = String #31 // 張三 #3 = Fieldref #12.#32 // com/brilliantstar/cimc/im/desktop/Demo.name:Ljava/lang/String; #4 = Fieldref #33.#34 // java/lang/System.out:Ljava/io/PrintStream; #5 = String #35 // Hello World. #6 = Methodref #36.#37 // java/io/PrintStream.println:(Ljava/lang/String;)V #7 = Class #38 // java/lang/StringBuilder #8 = Methodref #7.#30 // java/lang/StringBuilder."<init>":()V #9 = String #39 // Hello #10 = Methodref #7.#40 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #11 = Methodref #7.#41 // java/lang/StringBuilder.toString:()Ljava/lang/String; #12 = Class #42 // com/brilliantstar/cimc/im/desktop/Demo #13 = Class #43 // java/lang/Object #14 = Utf8 name #15 = Utf8 Ljava/lang/String; #16 = Utf8 <init> #17 = Utf8 ()V #18 = Utf8 Code #19 = Utf8 LineNumberTable #20 = Utf8 LocalVariableTable #21 = Utf8 this #22 = Utf8 Lcom/brilliantstar/cimc/im/desktop/Demo; #23 = Utf8 main #24 = Utf8 ([Ljava/lang/String;)V #25 = Utf8 args #26 = Utf8 [Ljava/lang/String; #27 = Utf8 sayHello #28 = Utf8 SourceFile #29 = Utf8 Demo.java #30 = NameAndType #16:#17 // "<init>":()V #31 = Utf8 張三 #32 = NameAndType #14:#15 // name:Ljava/lang/String; #33 = Class #44 // java/lang/System #34 = NameAndType #45:#46 // out:Ljava/io/PrintStream; #35 = Utf8 Hello World. #36 = Class #47 // java/io/PrintStream #37 = NameAndType #48:#49 // println:(Ljava/lang/String;)V #38 = Utf8 java/lang/StringBuilder #39 = Utf8 Hello #40 = NameAndType #50:#51 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #41 = NameAndType #52:#53 // toString:()Ljava/lang/String; #42 = Utf8 com/brilliantstar/cimc/im/desktop/Demo #43 = Utf8 java/lang/Object #44 = Utf8 java/lang/System #45 = Utf8 out #46 = Utf8 Ljava/io/PrintStream; #47 = Utf8 java/io/PrintStream #48 = Utf8 println #49 = Utf8 (Ljava/lang/String;)V #50 = Utf8 append #51 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #52 = Utf8 toString #53 = Utf8 ()Ljava/lang/String; { ===============欄位區域(用來列舉該類中的各個欄位)=================== private java.lang.String name; descriptor: Ljava/lang/String; flags: ACC_PRIVATE public com.brilliantstar.cimc.im.desktop.Demo(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: ldc #2 // String 張三 7: putfield #3 // Field name:Ljava/lang/String; 10: return LineNumberTable: line 19: 0 line 20: 4 LocalVariableTable: Start Length Slot Name Signature 0 11 0 this Lcom/brilliantstar/cimc/im/desktop/Demo; ===============方法區域(用來列舉該類中的各個方法)========================= public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #5 // String Hello World. 5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 23: 0 line 24: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 args [Ljava/lang/String; private void sayHello(); descriptor: ()V flags: ACC_PRIVATE Code: stack=3, locals=1, args_size=1 0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #7 // class java/lang/StringBuilder 6: dup 7: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V 10: ldc #9 // String Hello 12: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: aload_0 16: getfield #3 // Field name:Ljava/lang/String; 19: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 22: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 25: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 28: return LineNumberTable: line 27: 0 line 28: 28 LocalVariableTable: Start Length Slot Name Signature 0 29 0 this Lcom/brilliantstar/cimc/im/desktop/Demo; } SourceFile: "Demo.java"
以其中的sayHello()方法為例,除了方法描述以及訪問許可權之外,方法中還包括最為重要的程式碼區域。
1).程式碼區域一開始會宣告該方法中的運算元棧(stack=3) 和區域性變數數目(locals=1)的最大值,以及該方法接收引數的個數(args_size=1)這裡區域性變數指的是位元組碼中的區域性變數,而非Java程式中的區域性變數。
2).接下來是該方法的位元組碼,每條位元組碼均標註了對應的偏移量,這是用來定位位元組碼的。
3).接下來的行數表(LineNumberTable)則是Java源程式到位元組碼偏移量的對映。行數表和區域性變數均屬於除錯資訊,Java虛擬機器並不要求class檔案必備這些資訊。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28624388/viewspace-2213687/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java 虛擬機器經典六問Java虛擬機
- Java虛擬機器(六):類載入機制Java虛擬機
- Dalvik虛擬機器、Java虛擬機器與ART虛擬機器虛擬機Java
- java虛擬機器和Dalvik虛擬機器Java虛擬機
- Android 虛擬機器 Vs Java 虛擬機器Android虛擬機Java
- Java 虛擬機器之四:Java類載入機制Java虛擬機
- 深入理解虛擬機器之虛擬機器效能監控和故障處理工具虛擬機
- 虛擬化技術之kvm虛擬機器建立工具virt-install虛擬機
- 虛擬化技術之kvm虛擬機器建立工具qemu-kvm虛擬機
- Java虛擬機器(JVM)Java虛擬機JVM
- java~graalVM虛擬機器JavaLVM虛擬機
- Java虛擬機器系列之垃圾回收機制(2)Java虛擬機
- Java虛擬機器之垃圾回收演算法Java虛擬機演算法
- Java虛擬機器之記憶體區域Java虛擬機記憶體
- VMware 虛擬機器一鍵去虛擬化工具虛擬機
- Java 虛擬機器之三:Java虛擬機器的記憶體結構Java虛擬機記憶體
- 深入理解java虛擬機器之垃圾收集器Java虛擬機
- 深入理解Java虛擬機器之效能監控與故障處理工具Java虛擬機
- Java虛擬機器16:MetaspaceJava虛擬機
- 備戰- Java虛擬機器Java虛擬機
- 深入理解虛擬機器之虛擬機器類載入機制虛擬機
- 深入理解Java虛擬機器筆記之六記憶體分配與回收策略Java虛擬機筆記記憶體
- CrossOver for Mac(Windows虛擬機器工具)ROSMacWindows虛擬機
- 深入Java虛擬機器之 -- 總結面試篇Java虛擬機面試
- 深入理解Java虛擬機器之實戰OutOfMemoryErrorJava虛擬機Error
- Java虛擬機器之Class類檔案結構Java虛擬機
- 深入理解Java虛擬機器之垃圾回收篇Java虛擬機
- Java基礎:Java虛擬機器(JVM)Java虛擬機JVM
- 工具資源系列之給虛擬機器裝個centos虛擬機CentOS
- 虛擬機器故障與故障處理工具之指令篇虛擬機
- 詳解Java 虛擬機器(第②篇)——HotSpot 虛擬機器物件Java虛擬機HotSpot物件
- java虛擬機器指令常量部分Java虛擬機
- 深入理解java虛擬機器Java虛擬機
- Java 虛擬機器診斷利器Java虛擬機
- Java虛擬機器是什麼?Java虛擬機
- 深入理解Java虛擬機器之自己編譯JDKJava虛擬機編譯JDK
- 深入學習Java虛擬機器——虛擬機器位元組碼執行引擎Java虛擬機
- 虛擬機器之介紹_2.0虛擬機