JDK1.8关于运行时常量池, 字符串常量池的要点

17 篇文章 2 订阅

网上关于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

  • 42
    点赞
  • 210
    收藏
    觉得还不错? 一键收藏
  • 45
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 45
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值