初识字节码文件--Java
1,问题:请问以下代码,每行创建了几个对象?
public static void main(String[] args) {
String a = "你好";
String b = new String("你好");
String c = "你" + "好";
}
如何查看字节码
方法一:编译命令
使用 javac
命令编译你的Java源文件
javac YourClass.java
使用 javap
命令,查看字节码
javap -c YourClass
方法一:机智使用插件
jclasslib
插件使用方法
(1) 选中编译后的class文件
(2) 打开view窗口,点击show Bytecode With Jclasslib
效果如下:
下面对该字节码进行详解
0 ldc #7 <你好>
将常量池中索引为7的字符串“你好”加载到操作数栈中。
ldc
指令用于加载常量。在这里,它加载字符串常量你好
,该常量在常量池中索引为7
2 astore_1
astore_1
:将操作数栈顶部的值(“你好”)存储到局部变量表的索引1处。
astore_1
将栈顶的引用(即刚刚加载的你好
字符串)存储到局部变量表中的第一个位置。
3 new #9 <java/lang/String>
new #9 <java/lang/String>
:创建一个新的 String
对象实例。
new
指令用于创建一个新的对象,这里创建的是java/lang/String
类型的对象。常量池中的索引9
指向String
类。
6 dup
dup
:复制操作数栈顶部的值(新创建的 String
对象的引用),以便后续调用构造函数时使用。
dup
指令复制栈顶的引用。此时,栈顶是新创建的String
对象的引用,复制后栈顶有两个相同的引用。
7 ldc #7 <你好>
ldc #7 <你好>
:再次将常量池中的字符串“你好”加载到操作数栈中。
- 这里再次加载字符串常量
你好
,与第一行相同。
9 invokespecial #11 <java/lang/String.<init> : (Ljava/lang/String;)V>invokespecial
:调用 String
类的构造函数,传入之前加载的字符串“你好”。
invokespecial
指令调用构造方法。在这里,调用String
类的构造方法,将刚刚加载的你好
字符串传入,以初始化String
对象。
12 astore_2
astore_2
:将构造函数返回的 String
对象引用存储到局部变量表的索引2处。
astore_2
将构造出来的String
对象存储到局部变量表中的第二个位置。
13 ldc #7 <你好>
ldc #7 <你好>
:再次将常量池中的字符串“你好”加载到操作数栈中。
- 再次加载字符串常量
你好
,此时是为了将其存储到第三个局部变量中。
15 astore_3
astore_3
:将操作数栈顶部的值(“你好”)存储到局部变量表的索引3处。
astore_3
将栈顶的字符串常量你好
存储到局部变量表中的第三个位置。
16 return
return
:结束方法的执行,返回到调用者。
return
指令结束方法执行,返回到调用者。
由上可以看出,该代码一共只创建了两个对象
第一个对象:通过 ldc #7 <你好>
加载的字符串常量 你好
。这个常量在运行时会被视为一个对象,虽然它是一个字符串字面量,但在常量池中会被视为一个 String
对象。
第二个对象:通过 new
指令创建的 java/lang/String
对象。这是使用构造方法 String.<init>
初始化的对象。