JVM 编译优化 静态常量会被添加到当前类的“常量池”中,无需加载引用类(常量不加载/常量找不到/常量不更新)

14 篇文章 0 订阅

标题有点绕,意思是说如果A类中定义了一个常量,且这个常量是一个“编译期常量”,那么当其他类在引用这个常量的时候。A类本身可以不被JVM加载,这个常量可以被直接引用。

是不是更绕了,怎么还多出来一个“编译期常量”。即在编译期即可确定常量值。直接说重点,JVM这个编译优化会引起令人匪夷所思的BUG。让你查也查不到。

还是要回到标题,不加载A类就能直接引用A类的常量。这个常量会被存在调用类的常量池中。这样很容易让我想到既然是在编译期就存到了调用类中,那么如果编译的时候和运行的时候A类发生了变化,常量的值变了,在调用类没有重新编译的情况下,调用类就会引用到一个错误常量值。JVM真的会让这种事发生吗?!

用代码说话:

/**
 * @Author: tiantao
 * @Date: 2019/1/16 10:37 AM
 * @Version 1.0
 */
public class StaticClass {
    static {
        System.out.println("StaticClass loading...");
    }

    public static String VALUE = "static value loading A";

    public static final String FIANL_VALUE = "fianl value loading A";
}
/**
 * @Author: tiantao
 * @Date: 2019/1/16 10:38 AM
 * @Version 1.0
 */
public class StaticClassLoadTest {

    public static void main(String[] args) {
        System.out.println("StaticClassLoadTest...");
        printStaticVar();
    }

    private static void printStaticVar() {

        System.out.println(StaticClass.FIANL_VALUE);

        System.out.println(StaticClass.VALUE);

    }
}

执行结果:

StaticClassLoadTest...
fianl value loading A
StaticClass loading...
static value loading A

说明一下 StaticClass类的FIANL_VALUE是静态常量 而 VALUE 只是静态变量 或者说类变量。

从输出结果可以看出 在打印FIANL_VALUE的时候并没有加载StaticClass类,而是在需要调用到类变量的时候才加载的。

以上只是说明了加载顺序,但是不能说明静态常量 也就是例子中的FIANL_VALUE是被放到了调用类StaticClassLoadTest的常量池中。

接下来我们做如下操作。

1.备份当前的StaticClass的class文件。

2.修改StaticClass

/**
 * @Author: tiantao
 * @Date: 2019/1/16 10:37 AM
 * @Version 1.0
 */
public class StaticClass {
    static {
        System.out.println("StaticClass loading...");
    }

    public static String VALUE = "static value loading B";

    public static final String FIANL_VALUE = "fianl value loading B";
}

执行结果:

StaticClassLoadTest...
fianl value loading B
StaticClass loading...
static value loading B

这个结果毋庸置疑,没毛病。

3.删除现在的StaticClass.class文件

4.将之前备份的StaticClass的副本.class重命名为:StaticClass.class

5.执行程序,看执行结果,见证奇迹:

StaticClassLoadTest...
fianl value loading B
StaticClass loading...
static value loading A

怎么可以这样!

曾经那个修改常量不生效的bug,本地测试怎么都不复现,一上生产死活不生效。我明明没有改调用类,谁知道调用者也要更新!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值