1、从字符串拼接学习字节码分析
public class JvmTest {
public void test() {
String s4 = new String("hel") + "lo";
}
}
先反汇编,到class文件所在目录打开控制台执行javap -c 类名
$ javap -c JvmTest
警告: 二进制文件JvmTest包含com.chen.base.jvm.JvmTest
Compiled from "JvmTest.java"
public class com.chen.base.jvm.JvmTest {
public com.chen.base.jvm.JvmTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void test();
Code:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: new #4 // class java/lang/String
10: dup
11: ldc #5 // String hel
13: invokespecial #6 // Method java/lang/String."<init>":(Ljava/lang/String;)V
16: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: ldc #8 // String lo
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: astore_1
28: return
}
接下来一个指令一个指令的分析,为什么new String("hel") + "lo";
创建了两个对象。
行号 | 指令 | 含义 |
---|---|---|
13 | new | 堆中创建一个StringBuilder对象,并把堆中此对象地址压入栈顶 |
14 | dup | 复制栈顶的值,压入栈顶 |
15 | invokespecial | 初始化StringBuilder,对象创建都是先分配内存,再初始化 |
16 | new | 堆中创建一个String对象,并把堆中此对象地址压入栈顶 |
17 | dup | 复制栈顶的值,压入栈顶 |
18 | ldc | 从常量池取出字符串"hel"并压入栈顶 |
19 | invokespecial | 和前面一样,先分配地址,再调用String的初始化方法,把"hel"压入new的对象中,注意看19行注释,初始化时有传参(Ljava/lang/String;),15行是"" |