该文章,为网上查看以及B站的学习视频过程中的记录。
JVM指令
-xx:+TraceClassLoading , 用于追踪类的加载信息并打印出来
最先加载java.lang.Object
这里最后加载了我们自定义的父类和子类,并输出结果
-XX:+ < jvm_optional > ,开启optional选项,就比如上面的TraceClassLoading
-XX:- < jvm_optional > ,表示关闭jvm_optional选项
-XX:< optional > = < value > ,表示将optional选项的值设置为value,我们配置IDEA的时候设置jvm运行空间的时候用到这个指令
常量
public class finalClassDemo {
public static void main(String[] args) {
System.out.println(Demo.string);
}
}
class Demo{
public static final String string= "I am final string";
static {
System.out.println("I am demo static method");
}
}
上面main中虽然调用了Demo中的final修饰的静态变量string,但是Demo并没有被初始化,的原因是:
- 常量在编译阶段,会将常量存入,调用这个常量的 方法所在类的常量池中
- 本质上并没有调用类并没有直接引用到定义常量的类,因此并没有触发定义string的类
这里甚至可以删除Demo编译以后的字节码文件,也不会报错,注意这种情况只适用于常量情况
class Demo{
public static void main(String[] args) {
System.out.println(Demo.string);
}
public static final String string= "I am final string";
static {
System.out.println("I am demo static method");
}
}
这种写就会触发Demo的初始化了
助记符
public class finalClassDemo {
public static void main(String[] args) {
System.out.println(Demo.string);
System.out.println("-------------------");
System.out.println(Demo.i);
System.out.println("-------------------");
System.out.println(Demo.i2);
System.out.println("-------------------");
System.out.println(Demo.s);
}
}
class Demo{
public static final String string= "I am final string";
public static final int i2 = 20;
public static int i = 20;
public static short s = 1;
static {
System.out.println("I am demo static method");
}
}
javap -c 编译以后的.class文件
- ldc 表示将int,float,或者是string类型的常量值从常量池推送至栈顶
- bipush 表示将单字节(-128-127)的常量推送至栈顶
- sipush 表示将一个短整形常量(-32768 - 32767)推送至栈顶