今天聽的分享里在介紹String時,提到了javap,學習了好久的java,但是好像從來沒有了解過這個工具。
javap是JDK提供的一個命令行工具,javap能對給定的class文件提供的字節代碼進行反編譯。
通過它,可以對照源代碼和字節碼,從而了解很多編譯器內部的工作,對更深入地理解如何提高程序執行的效率等問題有極大的幫助。
使用格式
javap <options> <classes>
常用: javap -c -v 類名
-help --help -? 輸出此用法消息 -version 版本信息 -v -verbose 輸出附加信息 -l 輸出行號和本地變量表 -public 僅顯示公共類和成員 -protected 顯示受保護的/公共類和成員 -package 顯示程序包/受保護的/公共類 和成員 (默認) -p -private 顯示所有類和成員 -c 對代碼進行反匯編 -s 輸出內部類型簽名 -sysinfo 顯示正在處理的類的 系統信息 (路徑, 大小, 日期, MD5 散列) -constants 顯示最終常量 -classpath <path> 指定查找用戶類文件的位置 -cp <path> 指定查找用戶類文件的位置 -bootclasspath <path> 覆蓋引導類文件的位置
新建Hello.java
public class Hello { private Integer aa = 1; public String ss = "sss"; public static void main(String[] args) { System.out.println("Hello Java"); } }
不帶參數
javap Hello
Compiled from "Hello.java" public class Hello { public java.lang.String ss; public Hello(); public static void main(java.lang.String[]); }
c 對代碼進行反匯編
javap -c Hello
Compiled from "Hello.java" public class Hello { public java.lang.String ss; public Hello(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>": ()V 4: aload_0 5: iconst_1 6: invokestatic #2 // Method java/lang/Integer.valueOf: (I)Ljava/lang/Integer; 9: putfield #3 // Field aa:Ljava/lang/Integer; 12: aload_0 13: ldc #4 // String sss 15: putfield #5 // Field ss:Ljava/lang/String; 18: return public static void main(java.lang.String[]); Code: 0: getstatic #6 // Field java/lang/System.out:Ljava/ io/PrintStream; 3: ldc #7 // String Hello Java 5: invokevirtual #8 // Method java/io/PrintStream.printl n:(Ljava/lang/String;)V 8: return }
輸出附加信息
javap -v Hello
Classfile /D:/WWW/11/javap/Hello.class Last modified 2019-4-23; size 602 bytes MD5 checksum 9eb7401f16043460fa36db8275c0f7c4 Compiled from "Hello.java" public class Hello minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #10.#23 // java/lang/Object."<init>":()V #2 = Methodref #24.#25 // java/lang/Integer.valueOf:(I)Ljava/ lang/Integer; #3 = Fieldref #9.#26 // Hello.aa:Ljava/lang/Integer; #4 = String #27 // sss #5 = Fieldref #9.#28 // Hello.ss:Ljava/lang/String; #6 = Fieldref #29.#30 // java/lang/System.out:Ljava/io/Print Stream; #7 = String #31 // Hello Java #8 = Methodref #32.#33 // java/io/PrintStream.println:(Ljava/ lang/String;)V #9 = Class #34 // Hello #10 = Class #35 // java/lang/Object #11 = Utf8 aa #12 = Utf8 Ljava/lang/Integer; #13 = Utf8 ss #14 = Utf8 Ljava/lang/String; #15 = Utf8 <init> #16 = Utf8 ()V #17 = Utf8 Code #18 = Utf8 LineNumberTable #19 = Utf8 main #20 = Utf8 ([Ljava/lang/String;)V #21 = Utf8 SourceFile #22 = Utf8 Hello.java #23 = NameAndType #15:#16 // "<init>":()V #24 = Class #36 // java/lang/Integer #25 = NameAndType #37:#38 // valueOf:(I)Ljava/lang/Integer; #26 = NameAndType #11:#12 // aa:Ljava/lang/Integer; #27 = Utf8 sss #28 = NameAndType #13:#14 // ss:Ljava/lang/String; #29 = Class #39 // java/lang/System #30 = NameAndType #40:#41 // out:Ljava/io/PrintStream; #31 = Utf8 Hello Java #32 = Class #42 // java/io/PrintStream #33 = NameAndType #43:#44 // println:(Ljava/lang/String;)V #34 = Utf8 Hello #35 = Utf8 java/lang/Object #36 = Utf8 java/lang/Integer #37 = Utf8 valueOf #38 = Utf8 (I)Ljava/lang/Integer; #39 = Utf8 java/lang/System #40 = Utf8 out #41 = Utf8 Ljava/io/PrintStream; #42 = Utf8 java/io/PrintStream #43 = Utf8 println #44 = Utf8 (Ljava/lang/String;)V { public java.lang.String ss; descriptor: Ljava/lang/String; flags: ACC_PUBLIC public Hello(); 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: iconst_1 6: invokestatic #2 // Method java/lang/Integer.valueO f:(I)Ljava/lang/Integer; 9: putfield #3 // Field aa:Ljava/lang/Integer; 12: aload_0 13: ldc #4 // String sss 15: putfield #5 // Field ss:Ljava/lang/String; 18: return LineNumberTable: line 1: 0 line 2: 4 line 3: 12 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 #6 // Field java/lang/System.out:Ljav a/io/PrintStream; 3: ldc #7 // String Hello Java 5: invokevirtual #8 // Method java/io/PrintStream.prin tln:(Ljava/lang/String;)V 8: return LineNumberTable: line 5: 0 line 6: 8 } SourceFile: "Hello.java"
輸出行號和本地變量表
javap -l Hello
Compiled from "Hello.java" public class Hello { public java.lang.String ss; public Hello(); LineNumberTable: line 1: 0 line 2: 4 line 3: 12 public static void main(java.lang.String[]); LineNumberTable: line 5: 0 line 6: 8 }
javap -p Hello
Compiled from "Hello.java" public class Hello { private java.lang.Integer aa; public java.lang.String ss; public Hello(); public static void main(java.lang.String[]); }
javap -public Hello
Compiled from "Hello.java" public class Hello { public java.lang.String ss; public Hello(); public static void main(java.lang.String[]); }
javap -private Hello
Compiled from "Hello.java" public class Hello { private java.lang.Integer aa; public java.lang.String ss; public Hello(); public static void main(java.lang.String[]); }
輸出內部類型簽名
javap -s Hello
Compiled from "Hello.java" public class Hello { public java.lang.String ss; descriptor: Ljava/lang/String; public Hello(); descriptor: ()V public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V }
顯示正在處理的類的
javap -sysinfo Hello
Classfile /D:/WWW/11/javap/Hello.class Last modified 2019-4-23; size 602 bytes MD5 checksum 9eb7401f16043460fa36db8275c0f7c4 Compiled from "Hello.java" public class Hello { public java.lang.String ss; public Hello(); public static void main(java.lang.String[]); }
