javap是JDK自带的反汇编器,可以查看java编译器为我们生成的字节码。通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。
语法:
英文说明:
C:\>javap -help
Usage: javap ...
where options include:
-c Disassemble the code
-classpath Specify where to find user class files
-extdirs Override location of installed extensions
-help Print this usage message
-J Pass 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 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 classJAVAPTest {public static voidmain(String[] args) {
}public staticString contactWithStringNoLoopNoPara() {
String s= "This is " + " my " + "first JAVAP test code.";returns;
}public static String contactWithStringNoLoop(intcount) {
String s= "This is " + " my " + count + "th JAVAP test code.";returns;
}public static String contactWithStringLoop(intcount) {
String s= "";for (int i = 0; i < count; i++) {
s+=i;
}returns;
}public static String contactWithStringBufferLoop(intcount) {
StringBuffer sb= newStringBuffer();for (int i = 0; i < count; i++) {
sb.append(i);
}returnsb.toString();
}
}
先编译:javac JAVAPTest.java
执行反编译:javap -c JAVAPTest //注意这个地方不需要class后缀。
结果如下:
Compiled from "JAVAPTest.java"
public class JAVAPTest extendsjava.lang.Object{publicJAVAPTest();
Code:0: aload_01: invokespecial #1; //Method java/lang/Object."":()V
4: return
public static voidmain(java.lang.String[]);
Code:0: return
public staticjava.lang.String contactWithStringNoLoopNoPara();
Code:0: ldc #2; //String This is my first JAVAP test code.
2: astore_03: aload_04: areturnpublic static java.lang.String contactWithStringNoLoop(int);
Code:0: new #3; //class java/lang/StringBuilder
3: dup4: invokespecial #4; //Method java/lang/StringBuilder."":()V
7: ldc #5; //String This is my
9: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: iload_013: 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_125: aload_126: areturnpublic static java.lang.String contactWithStringLoop(int);
Code:0: ldc #10; //String
2: astore_13: iconst_04: istore_25: iload_26: iload_07: if_icmpge 35
10: new #3; //class java/lang/StringBuilder
13: dup14: invokespecial #4; //Method java/lang/StringBuilder."":()V
17: aload_118: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: iload_222: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: astore_129: iinc 2, 1
32: goto 5
35: aload_136: areturnpublic static java.lang.String contactWithStringBufferLoop(int);
Code:0: new #11; //class java/lang/StringBuffer
3: dup4: invokespecial #12; //Method java/lang/StringBuffer."":()V
7: astore_18: iconst_09: istore_210: iload_211: iload_012: if_icmpge 27
15: aload_116: iload_217: invokevirtual #13; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
20: pop21: iinc 2, 1
24: goto 10
27: aload_128: 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方法中,是循环拼接字符串。也是我们预想的步骤在执行。