常量与反编译及助记符
- 虚拟机参数
- 示例代码MyTest1
- 实例代码MyTest2
- 常量本质含义
- 助记符
- 对于静态字段,只有直接定义了该字段的类才会被初始化。
- 当一个类在初始化时,要求其父类全部都已经初始化完毕。
虚拟机参数:
-XX:+TraceClassLoading,虚拟机参数,用于追踪类的加载信息并打印出来。
-XX:+<option>,表示开启 option 选项。<option>=TraceClassLoading
-XX:-<option>,表示关闭 option 选项。
-XX:<option>=<value>,表示 option 选项的值设置为 value。
![d22d70bd0f5a2e4601a252e687911235.png](https://i-blog.csdnimg.cn/blog_migrate/e0bb1c29bc069fa6fbdd7c18727bcfbd.jpeg)
示例代码MyTest1:
public class MyTest1 {
public static void main(String[] args) {
System.out.println(MyChild.str);
}
}
class MyParent {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
class MyChild extends MyParent {
public static String str2 = "welcome";
static {
System.out.println("MyChild static block");
}
}
程序启动类的加载顺序:
首先加载的是 Object 类,..... 接下来加载启动的类(第六行)MyTest1,然后加载 MyParent,MyChild。
[Opened C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded java.lang.Object from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded java.io.Serializable from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded java.lang.Comparable from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded java.lang.CharSequence from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded com.example.jvm.MyTest1 from file:/E:/ideaworkspace/jvm_lecture/target/classes/]
[Loaded sun.launcher.LauncherHelper$FXHelper from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded java.lang.Class$MethodArray from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded java.lang.Void from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded com.example.jvm.MyParent from file:/E:/ideaworkspace/jvm_lecture/target/classes/]
[Loaded com.example.jvm.MyChild from file:/E:/ideaworkspace/jvm_lecture/target/classes/]
MyParent static block
hello world
[Loaded java.lang.Shutdown from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
[Loaded java.lang.Shutdown$Lock from C:Program FilesJavajdk1.8.0_181jrelibrt.jar]
示例代码MyTest2:
该示例代码通过 jvm 参数查看类加载,MyParent2 是没有被加载的。这说明了 MyParent2 是 被动使用。
public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.str);
}
}
class MyParent2 {
public static final String str = "hello world";
public static final short s = 10;
public static final int i = 100;
public static final int c = 0;
static {
System.out.println("MyParent2 static block");
}
}
输出结果:hello world
常量本质含义:
常量在编译阶段会存入到调用这个常量的方法所在的类的常量池中,本质上,调用类并没有直接引用到定义常量的类,因此并不会触发定义常量的类的初始化。
注意:这里指的是将常量存放到了 MyTest2 的常量池中,之后 MyTest2 与 MyParent2 就没有任何关系。
甚至,可以将 MyParent2 的 class 文件删除,程序仍然可以运行(这是因为已经将常量存放到了调用这个常量的方法所在类的常量池中,和这个 class 文件已经没有关联。)
助记符:
栈顶:表示即将进行使用。
javap -c ... 进行反编译
ldc 表示将 int,float 或是 String 类型的常量值从常量池中推送至栈顶。
aload:从局部变量表的相应位置装载一个对象引用到操作数栈的栈顶
![8a19253145017ef952ad87025b10cfb4.png](https://i-blog.csdnimg.cn/blog_migrate/a206c55a33cb261bd7621857353cfad8.jpeg)
bipush 表示将单字节(-128 ~ 127)的常量值推送至栈顶
![e43c042387184e247b478a9548bb5131.png](https://i-blog.csdnimg.cn/blog_migrate/62c2bf53fc5e0d7bc0a3120734405a73.jpeg)
sipush 表示将一个短整型常量值 (-32768 ~ 32767)推送至栈顶
![efe0fb591ff7044669155c33b2e96d16.png](https://i-blog.csdnimg.cn/blog_migrate/e944ac03803d7957c5266187aca9cfbf.jpeg)
iconst_0 表示将int类型0推送至栈顶 (iconst_-1 ~ iconst_5)
![5341613acd7edee4fb13a138b2503719.png](https://i-blog.csdnimg.cn/blog_migrate/6d9e11d6a649aa742038c805c7f5bb2d.png)
![856937ef5515bd803fab10d95ebfee22.png](https://i-blog.csdnimg.cn/blog_migrate/e4a23d6db64d1bd3217a2b66b50a0f21.jpeg)
anewarry:表示创建一个引用类型的(如类、接口、数组)数组,并将引用值压入栈顶。
newarray:表示创建一个指定的原型类型(如int、float、char)的数组,并将其引用值压入栈顶。