查看字节码Javap

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class JavaP {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hel" + "lo";
String s3 = new String("Hello");
String s4 = "Hel" + new String("lo");
String s5 = s3.intern();
int i1 = 0;
int i2 = 1;

System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
System.out.println(s2 == s4);
System.out.println(s1 == s2);
System.out.println(s2 == s5);
System.out.println(i1 == i2);
}
}

查看字节码

1
javap -v JavaP.class

字节码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Constant pool:(常量池)
#2 = String #36 // Hello
#3 = Class #37 // java/lang/String
#5 = Class #39 // java/lang/StringBuilder
#7 = String #40 // Hel
#9 = String #42 // lo
{
stack=4, locals=8, args_size=1
0: ldc #2 // String Hello (加载常量池的#2号字符串压入栈)
2: astore_1 (将上一步加载的引用变量赋值给变量1,即s1【参照LocalVariableTable的slot数值】)
3: ldc #2 // String Hello (加载常量池的#2号字符串压入栈)
5: astore_2 (将上一步加载的引用变量赋值给变量2,即s2【参照LocalVariableTable的slot数值】)
6: new #3 // class java/lang/String (创建#3号的实例:java/lang/String)
9: dup (复制上一步创建的对象的引用压入栈)
10: ldc #2 // String Hello (加载常量池的#2号字符串压入栈)
12: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V (调用String的init方法,将上一步加载入栈的引用作为参数传入init方法)
15: astore_3 (将上一步返回的引用变量赋值给变量3,即s3【参照LocalVariableTable的slot数值】)
16: new #5 // class java/lang/StringBuilder(创建#5号的实例:java/lang/StringBuilder)
19: dup (复制上一步创建的对象引用压入栈)
20: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V (调用StringBuilder的init方法)
23: ldc #7 // String Hel (加载常量池#7号字符串压入栈)
25: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;(调用StringBuilder的append方法,将上一步加载的引用作为参数传入append方法)
28: new #3 // class java/lang/String (创建#3号的实例:java/lang/String)
31: dup (复制上一步创建的对象的引用压入栈)
32: ldc #9 // String lo (加载常量池#9号字符串压入栈)
34: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V (调用String的init方法,将上一步加载入栈的引用作为参数传入init方法)
37: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;(调用StringBuilder的append方法,将上一步加载的引用作为参数传入append方法)
40: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;(调用StringBuilder的toString方法)
43: astore 4 (将上一步返回的引用赋值给变量4,即s4【参照LocalVariableTable的slot数值】)
45: aload_3 (加载变量3压入栈)
46: invokevirtual #11 // Method java/lang/String.intern:()Ljava/lang/String; (调用String的intern方法)
49: astore 5 (将上一步返回的引用赋值给变量5,即s5【参照LocalVariableTable的slot数值】)
51: iconst_0 (将数字0压入栈)
52: istore 6 (将上一步加载的数字赋值给变量6,即i1【参照LocalVariableTable的slot数值】)
54: iconst_1 (将数字1压入栈)
55: istore 7 (将上一步加载的数字赋值给变量7,即i2【参照LocalVariableTable的slot数值】)
57: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream; (调用System的静态方法out)
60: aload_1 (加载变量1,即s1)
61: aload_2 (加载变量2,即s2)
62: if_acmpne 69(比较s1和s2是否不相等,如果不相等,跳转到63行指令,如果相等则继续下一步,if_acmpne和if_icmpne,a表示对象引用比较,I表示数字比较;if_acmpeq和if_acmpne,eq【equal】表示相等,ne【not equal】)
65: iconst_1 (将数字1压入栈)
66: goto 70 (跳转到64行指令)
69: iconst_0 (将数字0压入栈)
70: invokevirtual #13 // Method java/io/PrintStream.println:(Z)V
……
156: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream;
159: iload 6 (加载变量6,即i1)
161: iload 7 (加载变量7,即i2)
163: if_icmpne 170(比较i1和i2)
166: iconst_1
167: goto 171
170: iconst_0
171: invokevirtual #13 // Method java/io/PrintStream.println:(Z)V
……
150: return
LocalVariableTable:
Start Length Slot Name Signature
0 151 0 args [Ljava/lang/String;
3 148 1 s1 Ljava/lang/String;
6 145 2 s2 Ljava/lang/String;
16 135 3 s3 Ljava/lang/String;
45 106 4 s4 Ljava/lang/String;
51 100 5 s5 Ljava/lang/String;
54 121 6 i1 I
57 118 7 i2 I
}