浅谈jvm运行时常量池(基于jdk7)

本文详细介绍了JVM的运行时常量池,包括静态常量池和运行时常量池的动态性。讨论了字符串常量池中的对象共享,以及intern()方法的作用。同时强调了编译器对常量的优化,并指出new操作符创建的对象存放在堆中。最后,总结了常量池的关键点并提及了String#intern的深入解析。
摘要由CSDN通过智能技术生成

前言

在阅读文章之前,先来做一道题:下面代码会输出什么呢?

$ String a  ="abc";
$ String b = "abc";
$ System.out.println(a==b);

介绍

在上一篇文章中晚饭简单讲解了JVM是如何加载class文件的,浅解JVM加载class文件 | Mrsssswan.club
内存的控制权在于JVM,JVM在执行java程序时会把它管理的内存划分为不同的数据区

1
该图来源于JVM入门——运行时数据区 - OKevin - 博客园

静态常量池

加载class文件之后内存中会生成该类的对象,并把该对象实例放在堆中

堆中的对象是可以共享的,方法区也和堆一样,它用于存储已被JVM加载了的数据。这其中就有常量,静态变量。

运行时常量池是方法区的一部分。
在上面题目中,“abc”这个字符串是放在常量池中的,内存中只有一份,是“共享”的,所以a,b指向的是同一个,答案为true

隐隐预约懂了一丢丢?那再做个题
下面一共创建了几个对象呢??

$ String a  ="a"+"b"+"c";

赋值右边的“a”,“b”,“c”其实都是常量,编译时会进行优化,将它们的连接结果存储起来
2

当JVM执行到String a =“a”+“b”+"c"时,编译器会进行优化,相当于执行的是String a =“abc”,这时候就会在常量池中找,如果没有这个字符串,就会产生一个对象

所以,答案是只创建了一个对象

常量池的动态性

前面晚饭讲的是静态常量池,而运行期间也是可以放入新的常量的,称之为运行时常量池。可以使用String类的intern()方法来实现

调用intern()方法中,如果常量池中已经包含String对象的字符串,返回该字符串,否则将String对象的字符串添加进池中,并返回其引用

$ String s1 = "abc";
$ String s2 = new String("abc");
$ s2 = s2.intern();
$ System.out.println(s1==s2);

输出为 true
一定得说清楚的一点就是,new出来的对象是在堆中分配的,所以下面这两条语句其实在不同内存区域中存放了不同的数据

$ String s1 = new String("abc");   //heap中创建一个String的实例
$ s1 = s1.intern();                    //常量池中存放abc这个字符串

一张图可能更清晰的说明

在这里插入图片描述
来源于String的final和String常量池 - SGY123 - 博客园

补充编译时变量

在前面讲到

$ String a  ="abc";
$ String b = "abc";
$ System.out.println(a==b);

会输出true,因为“abc”是常量,但如果改成这样结果还是会为true吗

$ String a ="a";
$ String b ="b";
$ String c ="c";
$ String s = a+b+c; 
$ String s1 = "abc";
$ System.out.println(s==s1); //true还是false???

a,b,c三个变量,都是不可预料的,编译器是编译时不能确定它的值是多少,只会在执行时创建新的String对象存储到堆中

4
晚饭自己画的图嘻嘻嘻~~~

所以,答案为false

总结

1.常量池中存储了编译器编译后的数据,而运行时常量池的常量,基本来源于各个class文件中的常量池,可以理解为方法区的“共享”.
2.程序运行期间,可以手动想常量池添加常量,例如调用String的intern()方法。
3.要注意区分new出来的对象是在堆中创建的
4.编译器会对常量进行优化,但编译期间无法确定变量的值

浅谈jvm运行时常量池就到这里了啊,有什么疑问可以发晚饭邮箱!~

晚饭后来看到一篇美团技术的文章,讲解的更清楚,看完文章后更是自愧不如,对比之下文章很不严谨
大家可以看下美图的这篇文章深入解析String#intern


晚饭邮箱:1520010400@qq.com


公众号

欢迎关注,微信公众号,获取最新文章

晚饭带你学Java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值