参考博客:https://www.cnblogs.com/qlqwjy/p/7586538.html
一、javap是jdk自带的反解析工具
它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。
二、javap参数说明
D:\test>javap -help
用法: javap <options> <classes>
其中, 可能的选项包括:
-help --help -? 输出此用法消息
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类
和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的
系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示最终常量
-classpath <path> 指定查找用户类文件的位置
-cp <path> 指定查找用户类文件的位置
-bootclasspath <path> 覆盖引导类文件的位置
三、应用举例
使用javap命令,分析字符串拼接时,何时使用“+”,何时需要使用StringBuilder
public class JavapExample {
public String contactString() {
return "contact " + "string";
}
public String contactStringWithPara(int count) {
return "contact string with " + count;
}
public String contactStringWithParaInLoop(int count) {
String str = "";
for (int x = 0; x < count; x++) {
str += x;
}
return str;
}
public String contactStringBuilderWithParaInLoop(int count) {
StringBuilder sb = new StringBuilder();
for (int x = 0; x < count; x++) {
sb.append(x);
}
return sb.toString();
}
}
对该类使用javac JavapExample.java编译之后
在Class文件目录下,输入javap -c JavapExample.class可以看到控制台打印如下:
D:\test>javap -c JavapExample.class
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
Compiled from "JavapExample.java"
public class JavapExample {
public JavapExample();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public java.lang.String contactString();
Code:
0: ldc #2 // String contact string
2: areturn
public java.lang.String contactStringWithPara(int);
Code:
0: new #3 // class java/lang/StringBuilder
3: dup
4: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
7: ldc #5 // String contact string with
9: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: iload_1
13: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
16: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
19: areturn
public java.lang.String contactStringWithParaInLoop(int);
Code:
0: ldc #9 // String
2: astore_2
3: iconst_0
4: istore_3
5: iload_3
6: iload_1
7: if_icmpge 35
10: new #3 // class java/lang/StringBuilder
13: dup
14: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: iload_3
22: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: astore_2
29: iinc 3, 1
32: goto 5
35: aload_2
36: areturn
public java.lang.String contactStringBuilderWithParaInLoop(int);
Code:
0: new #3 // class java/lang/StringBuilder
3: dup
4: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
7: astore_2
8: iconst_0
9: istore_3
10: iload_3
11: iload_1
12: if_icmpge 27
15: aload_2
16: iload_3
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
20: pop
21: iinc 3, 1
24: goto 10
27: aload_2
28: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: areturn
}
1. contactString()
0: ldc #2 // String contact string
字符串常量拼接,无需使用StringBuilder。
2. contactStringWithPara(int count)
0: new #3 // class java/lang/StringBuilder
字符串常量与变量拼接,编译器自动使用了StringBuilder,所以无需在代码中定义StringBuilder。
3. contactStringWithParaInLoop(int count)
5: iload_3
6: iload_1
7: if_icmpge 35
10: new #3 // class java/lang/StringBuilder
13: dup
14: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: iload_3
22: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: astore_2
29: iinc 3, 1
32: goto 5
在循环中拼接字符串,每次循环都需要重新创建一次StringBuilder对象,并调用StringBuilder.toString()方法赋值,造成了资源浪费,所以建议代码中定义StringBuilder完成字符串的拼接。
4. contactStringBuilderWithParaInLoop(int count)
0: new #3 // class java/lang/StringBuilder
3: dup
4: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
7: astore_2
8: iconst_0
9: istore_3
10: iload_3
11: iload_1
12: if_icmpge 27
15: aload_2
16: iload_3
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
20: pop
21: iinc 3, 1
24: goto 10
27: aload_2
28: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
使用StringBuilder在循环中拼接字符串,反编译之后发现,只创建了一次StringBuilder对象,并执行了一次StringBuilder.toString()方法,所以此处使用StringBuilder是正确的。