javap的基本用法


javap是JDK自帶的反匯編器,可以查看java編譯器為我們生成的字節碼。通過它,我們可以對照源代碼和字節碼,從而了解很多編譯器內部的工作。
語法:
  javap [ 命令選項 ] class. . .
  javap 命令用於解析類文件。其輸出取決於所用的選項。若沒有使用選項,javap 將輸出傳遞給它的類的 public 域及方法。javap 將其輸出到標准輸出設備上。
命令選項
  -help 輸出 javap 的幫助信息。
  -l 輸出行及局部變量表。
  -b 確保與 JDK 1.1 javap 的向后兼容性。
  -public 只顯示 public 類及成員。
  -protected 只顯示 protected 和 public 類及成員。
  -package 只顯示包、protected 和 public 類及成員。這是缺省設置。
  -private 顯示所有類和成員。
  -J[flag] 直接將 flag 傳給運行時系統。
  -s 輸出內部類型簽名。
  -c 輸出類中各方法的未解析的代碼,即構成 Java 字節碼的指令。
  -verbose 輸出堆棧大小、各方法的 locals 及 args 數,以及class文件的編譯版本
  -classpath[路徑] 指定 javap 用來查找類的路徑。如果設置了該選項,則它將覆蓋缺省值或 CLASSPATH 環境變量。目錄用冒號分隔。
   -bootclasspath[路徑] 指定加載自舉類所用的路徑。缺省情況下,自舉類是實現核心 Java 平台的類,位於 jrelib下面。
  -extdirs[dirs] 覆蓋搜索安裝方式擴展的位置。擴展的缺省位置是 jrelibext。

 

英文說明:

C:\>javap -help
Usage: javap <options> <classes>...

where options include:
   -c                        Disassemble the code
   -classpath <pathlist>     Specify where to find user class files
   -extdirs <dirs>           Override location of installed extensions
   -help                     Print this usage message
   -J<flag>                  Pass <flag> directly to the runtime system
   -l                        Print line number and local variable tables
   -public                   Show only public classes and members
   -protected                Show protected/public classes and members
   -package                  Show package/protected/public classes
                             and members (default)
   -private                  Show all classes and members
   -s                        Print internal type signatures
   -bootclasspath <pathlist> Override location of class files loaded
                             by the bootstrap class loader
   -verbose                  Print stack size, number of locals and args for methods
                             If verifying, print reasons for failure

 

示例:

下面也經典的StringBuilder代替String做字符串的例子。

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

}

public static String contactWithStringNoLoopNoPara() {
String s = "This is " + " my " + "first JAVAP test code.";
return s;
}

public static String contactWithStringNoLoop(int count) {
String s = "This is " + " my " + count + "th JAVAP test code.";
return s;
}

public static String contactWithStringLoop(int count) {
String s = "";
for (int i = 0; i < count; i++) {
s += i;
}
return s;
}

public static String contactWithStringBufferLoop(int count) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
sb.append(i);
}
return sb.toString();
}
}

 

先編譯:javac JAVAPTest.java

執行反編譯:javap -c JAVAPTest         //注意這個地方不需要class后綴。

結果如下:

Compiled from "JAVAPTest.java"
public class JAVAPTest extends java.lang.Object{
public JAVAPTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public static void main(java.lang.String[]);
Code:
0: return

public static java.lang.String contactWithStringNoLoopNoPara();
Code:
0: ldc #2; //String This is my first JAVAP test code.
2: astore_0
3: aload_0
4: areturn

public static java.lang.String contactWithStringNoLoop(int);
Code:
0: new #3; //class java/lang/StringBuilder
3: dup
4: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
7: ldc #5; //String This is my
9: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: iload_0
13: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
16: ldc #8; //String th JAVAP test code.
18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_1
25: aload_1
26: areturn

public static java.lang.String contactWithStringLoop(int);
Code:
0: ldc #10; //String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: iload_0
7: if_icmpge 35
10: new #3; //class java/lang/StringBuilder
13: dup
14: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
17: aload_1
18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: iload_2
22: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: astore_1
29: iinc 2, 1
32: goto 5
35: aload_1
36: areturn

public static java.lang.String contactWithStringBufferLoop(int);
Code:
0: new #11; //class java/lang/StringBuffer
3: dup
4: invokespecial #12; //Method java/lang/StringBuffer."<init>":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: iload_0
12: if_icmpge 27
15: aload_1
16: iload_2
17: invokevirtual #13; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
20: pop
21: iinc 2, 1
24: goto 10
27: aload_1
28: invokevirtual #14; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
31: areturn

}

有這個結果我們可以知道。
1。contactWithStringNoLoopNoPara方法中,代碼里面是字符串拼接,貌似需要是用StringBuilder替換的好。其實在看了上面的反編譯結果后,已經自動組合成一個固定字符串了。因此完全沒有必要使用StringBuilder。

0: ldc #2; //String This is my first JAVAP test code.
2。contactWithStringNoLoop方法中,因為使用到了變量,貌似需要是用StringBuilder替換的好。其實在看了上面的反編譯結果后,已經自動使用了StringBuilder。所以代碼也沒有必要使用StringBuilder。

 

3. contactWithStringLoop方法中,是循環拼接字符串,貌似需要是用StringBuilder替換的好。看了反編譯后,每個循環里面都各自生成了一個StringBuilder,並將StringBuilder.toString()防賦值給我們的Sring變量。而我們希望的是只生成一個StringBuilder對象。因此改為StringBuilder的好。循環的時候改為contactWithBufferLoop的方法最好。

 

4.contactWithBufferLoop方法中,是循環拼接字符串。也是我們預想的步驟在執行。
————————————————
版權聲明:本文為CSDN博主「步行者」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/hantiannan/java/article/details/7659904


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM