JDK1.8关于运行时常量池, 字符串常量池的要点[通俗易懂]

2022-09-19 20:03:11 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

网上关于jdk 1.8的各种实验, 结论鱼龙混杂 , 很多都相矛盾,网上有的实验也被后人测试出了不同的结果

很多都分辨不了真假, 这里记录一下网络上正确的结论, 欢迎指正!

首先自行区分运行时常量池Class文件常量池(静态常量池)的概念, JVM内存模型 ,方法区与永久代的区别, 有些在我的其他博客有介绍, 连接在文尾

JDK1.7之前运行时常量池逻辑包含字符串常量池存放在方法区, 此时hotspot虚拟机对方法区的实现为永久代

JDK1.7 字符串常量池被从方法区拿到了堆中, 这里没有提到运行时常量池,也就是说字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代

JDK1.8 hotspot移除了永久代元空间(Metaspace)取而代之, 这时候字符串常量池还在堆, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间(Metaspace)

  • 对于直接做 运算的两个字符串(字面量)常量,并不会放入字符串常量池中,而是直接把运算后的结果放入字符串常量池中 (String s = “abc” “def”, 会直接生成“abcdef”字符串常量 而不把 “abc” “def”放进常量池)
  • 对于先声明的字符串字面量常量,会放入字符串常量池,但是若使用字面量的引用进行运算就不会把运算后的结果放入字符串常量池中了 (String s = new String(“abc”) new String(“def”),在构造过程中不会生成“abcdef”字符串常量)
  • 总结一下就是JVM会对字符串常量的运算进行优化,未声明的,只放结果;已经声明的,只放声明
  • 常量池中同时存在字符串常量和字符串引用。直接赋值和用字符串调用String构造函数都可能导致常量池中生成字符串常量;而intern()方法会尝试将堆中对象的引用放入常量池
  • String str1 = “a”; String str2 = “b”; String str4 = str1 str2; //该语句只在堆中生成一个对象(str4) 这句被Java编译器做了优化, 实际上使用StringBuilder实现的(不在堆里生成str1和str2对象)
  • String str5 = new String(“ab”);(字符串常量池中不存在”ab”时)在字符换常量池中创建”ab”对象,在堆中生成了一个对象str5, str5指向堆上new的对象,而str5内部的char value[]则指向常量池中的char value[] 关于这个问题可以参考这篇博客:new String()究竟创建几个对象?

附上自己相关的几篇博客:

永久代->元空间 https://blog.csdn.net/q5706503/article/details/84621210

string.intern https://blog.csdn.net/q5706503/article/details/84586219

JVM内存空间模型 https://blog.csdn.net/q5706503/article/details/84614158

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/164779.html原文链接:https://javaforall.cn

0 人点赞