02.常量的本质含义与反编译及助记符
VM 参数
-XX:+<option>
- 表示开启 option 选项
-XX:-<option>
- 关闭 option 选项
-XX:<option>=<value>
- 将 option 选项的值设置为 value
- 比如堆空间大小
-XX:+TeaceClassLoading
用于追踪类的加载信息并打印出来
[Opened C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar]
[Loaded java.io.Serializable from C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar]
[Loaded java.lang.Comparable from C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar]
...
常量的本质
- 常量在编译阶段会存入到调用这个常量的方法所在的类的常量池
- 本质上,调用类并没有直接引用到定义常量的类,因此并不会触发定义常量的类的初始化
- 这里指的是将常量存放到了 MyTest2 的常量池中,之后 MyTest2 与 MyParent2 就没有任何关系了
public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.str);
}
}
class MyParent2 {
public static final String str = "hello world";
static {
System.out.println("MyParent2 static block");
}
}
使用以下命令反编译后
javap -c MyTest2
得到
Compiled from "MyTest2.java"
public class cn.duniqb.jvm.classloader.MyTest2 {
public cn.duniqb.jvm.classloader.MyTest2();
public static void main(java.lang.String[]);
}
D:\code\IdeaProjects\jvm\ssy-jvm\target\classes\cn\duniqb\jvm\classloader>javap -c MyTest2.class
Compiled from "MyTest2.java"
public class cn.duniqb.jvm.classloader.MyTest2 {
public cn.duniqb.jvm.classloader.MyTest2();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String hello world
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
可以看到,在 main 方法中,String 的值已经是 hello world 了
助记符:
- ldc
- 表示将 int,float 或 String 类型的常量值从常量池中推送至栈顶
- bipush
- 表示将单字节 (-128 ~ 127) 的常量值推送至栈顶
- sipush
- 表示将一个短整型常量值 (-32768 ~ 32767) 推送至栈顶
- iconst_1
- 表示将 int 类型的 1 推送至栈顶
- 一共是
iconst_1 ~ iconst_5
,其他变为 bipush
没有修不好的电脑