在jvm参数当中一共有以下三种
- -XX:+ 加号表示开启选项
- -XX:- 减号表示关闭选项
- -XX:=:表示将option的值设置为value
- 在idea中添加vm option参数,–XX:+TraceClassLoading用于打印类加载信息
如下:
测试java中静态常量和静态变量区别的样例,表明两者加载时的区别。
StaticClass类中定义了静态常量FIANL_VALUE和静态变量VALUE,静态代码块的打印语句表示类被加载:
public class StaticClass {
static {
System.out.println("StaticClass loading...");
}
public static String VALUE = "static value loading";
public static final String FIANL_VALUE = "fianl value loading";
}
StaticClassLoadTest类用于测试静态变量的加载:
public class StaticClassLoadTest {
public static void main(String[] args) {
System.out.println("StaticClassLoadTest...");
printStatic();
//printnewStatic();
}
private static void printStatic() {
System.out.println(StaticClass.FIANL_VALUE);
System.out.println(StaticClass.VALUE);
}
private static void printnewStatic() {
System.out.println(StaticClass.FINAL_VALUE_STR);
System.out.println(StaticClass.VALUE);
}
}
[Loaded java.net.InetAddress$Cache$Type from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.InetAddressImplFactory from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded com.xxx.domain.StaticClassLoadTest from file:/D:/work/fix/xxx.ui/target/classes/]
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.InetAddressImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.Inet6AddressImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded sun.net.spi.nameservice.NameService from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.InetAddress$2 from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
StaticClassLoadTest...
fianl value loading
[Loaded sun.net.util.IPAddressUtil from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.Inet4Address from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocksConsts from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded com.xxx.domain.StaticClass from file:/D:/work/fix/xxx.ui/target/classes/]
[Loaded java.net.SocketOptions from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
StaticClass loading...
[Loaded java.net.SocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
static value loading
输出显示在打印静态常量时,StaticClass类没有被加载,在输出静态变量的前才打印类加载信息。这表明类的未加载的情况下也能引用其静态常量信息,原因是因为常量值存储在JVM内存中的常量区中,在类不加载时即可访问。
注:经过编译优化,静态常量 FIANL_VALUE 已经存到NotInit类自身常量池中,不会加载StaticClass
但是不能说所有的静态常用访问都不需要类的加载,这里还要判断这个常量是否属于“编译期常量”,即在编译期即可确定常量值。如果常量值必须在运行时才能确定,如常量值是一个随机值,也会引起类的加载,如下:
public static final StringBuilder FINAL_VALUE_STR = new StringBuilder("new fianl value loading");
输出:
[Loaded com.xxx.domain.StaticClassLoadTest from file:/D:/work/fix/xxx.ui/target/classes/]
[Loaded sun.net.util.IPAddressUtil from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.Inet4Address from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocksConsts from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
StaticClassLoadTest...
[Loaded java.net.SocketOptions from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.AbstractPlainSocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.PlainSocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocksSocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.AbstractPlainSocketImpl$1 from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded com.xxx.domain.StaticClass from file:/D:/work/fix/xxx.ui/target/classes/]
StaticClass loading...
new fianl value loading
static value loading
总结:
final修饰的实例属性,在实例创建的时候才会赋值。
static修饰的类属性,在类加载的准备阶段赋初值,初始化阶段赋值。
static+final修饰的String类型或者基本类型常量,JVM规范是在初始化阶段赋值,但是HotSpot VM直接在准备阶段就赋值了。
static+final修饰的其他引用类型常量,赋值步骤和第二点的流程是一样的。
参考:你知道Java中final和static修饰的变量是在什么时候赋值的吗?_CoderW喜欢写博客的博客-CSDN博客