美文网首页
《深入Java虚拟机》代码2-7 String.intern()

《深入Java虚拟机》代码2-7 String.intern()

作者: kkyeer | 来源:发表于2018-09-17 22:40 被阅读0次

    环境说明

    openjdk7u11 自己从源码编译的版本

    源码

    参考书上的源码

    public class FunWithIntern {
        public static void main(String[] args) {
            String str1 = new StringBuilder("沙").append("发").toString();
            System.out.println(str1.intern() == str1);
    
            String str2 = new StringBuilder("ja").append("va").toString();
            System.out.println(str2.intern() == str2);
    
            String str3 = new StringBuilder("open").append("jdk").toString();
            System.out.println(str3.intern() == str3);
        }
    }
    

    上述程序运行的结果为

    true
    true
    false
    

    与书上的说明不符
    按书上的说明,由于jdk1.7中,String.intern()返回的是首次出现的字符串的引用,所以对于str1,由于str1即字符串”沙发“在环境中第一次出现,str1.intern()返回的是str1的引用,所以str1.intern()==str1结果为true
    问题出在str2,书上说字符串"java"不是在此方法中第一次出现,因此在运行此程序之前,即环境初始化时已有字符串"Java",所以理论str2.intern()==str2结果应为false,然而实际运行中,此方法仍旧为true,即环境中预先不存在此字符串,与书中描述不符

    探秘

    实际中,书中指的预先存在的字符串是在System类初始化中定义的,查看System类源码

    public final class System {
    
        /* register the natives via the static initializer.
         *
         * VM will invoke the initializeSystemClass method to complete             <===VM调用initializeSystemClass方法
         * the initialization for this class separated from clinit.
         * Note that to use properties set by the VM, see the constraints
         * described in the initializeSystemClass method.
         */
        private static native void registerNatives();
        static {
            registerNatives();
        }
    //...
        private static void initializeSystemClass() {
    //...
            sun.misc.VM.saveAndRemoveProperties(props);
            lineSeparator = props.getProperty("line.separator");
            sun.misc.Version.init();//                                             <===此方法中会调用sun.misc.Version.init()方法
       }
    }
    

    注意上面两处箭头注释 :VM调用initializeSystemClass方法=>此方法中会调用sun.misc.Version.init()方法,而sun.misc.Version类如下

    public class Version {
        private static final String launcher_name = "openjdk";
        private static final String java_version = "1.7.0-internal";
    //...
    }
    

    在某些环境中上面的launcher_name的值为"java",第一个程序运行时,"java"预先存在,str2.intern()==str2返回false
    我的openjdk中"java"预先不存在,str2.intern()==str2返回true,但str3.intern()==str3返回false

    参考 https://blog.csdn.net/w605283073/article/details/72753494

    相关文章

      网友评论

          本文标题:《深入Java虚拟机》代码2-7 String.intern()

          本文链接:https://www.haomeiwen.com/subject/lhqjnftx.html