虚拟机hotspot关于字符串的一些事

/**
 * Created by root on 20-12-26.
 */
public class Foo {
    public static void main(String[] args) throws InterruptedException {
        String s1 = new StringBuilder("go").append("od").toString();
        System.out.println(s1.intern() == s1);

        String s2 = new StringBuilder("ja").append("va").toString();
        System.out.println(s2.intern() == s2);

        String s3 = new StringBuilder("java.").append("version").toString();
        System.out.println(s3.intern() == s3);

        String s4 = new StringBuilder("open").append("jdk").toString();
        System.out.println(s4.intern() == s4);
    }
}
输出的结果:
true
false
false
true

为什么同样操作结果却不一样?
答案是:在jvm运行到这个main方法之前加载过java和java.version这两个字符串了。
那么问题来了,何时加载?以什么方式加载的呢?
PS : 知乎上R大在2016年已经有完整的解释了,链接在下方。

答案

是jvm在创建的时候,调用java的rt.jar包下面,
java.lang.System类中,initializeSystemClass静态方法。
在这里插入图片描述这个方法会调用sun.misc.Version.init()方法,然而Version.class的结构是这样的,如下图:
在这里插入图片描述

继续深究

我手边正好有jdk-8(jvm)的debug环境,就debug了一下,想找出在哪里调用的。出乎我的意料的是,跑出来的答案完全不一样,如下图:
在这里插入图片描述结果是:
java为true,openjdk为false,为什么呢?
我想坑定是sun.misc.Version这个类有啥问题,我立马打开
我的类,发现了端倪,如下图:
在这里插入图片描述好吧,我的launcher_name竟然是openjdk。原来如此!!!

最后的问题

何时调用?以什么方式调用的呢?直接上图吧,如下:
在这里插入图片描述在这里插入图片描述JavaCalls::call_static 这个方法是hotspot虚拟机调用jdk的惯用伎俩。
接着调用你的mainClass了,如下图:
在这里插入图片描述具体为啥要调用,这些东西,以后在研究吧,我要睡觉了。
R大还是牛逼啊,哈哈!

(R大)链接:https://www.zhihu.com/question/51102308
PS:祝大家圣诞 元旦快乐!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值