java字符串常量池保存在哪里?如何证明?

java字符串常量池保存在哪里?如何证明?

    有一次被问到java字符串常量池保存在哪里?如何证明?其实这个问题我想不会难倒大多数人,但是问题如何证明呢?我当时也一脸懵逼,因为确实不知道怎么证明,了解到的也只是从一些博客或贴子中得来,也不知是否正确。以下是经过一番学习整理后的一些个人结论。

    首先看看Oracle官方的说明,以下是JDK7 Java虚拟机(HotSpot)相关的一些较大更改,其中就有字符串常量池的说明。链接地址:https://docs.oracle.com/javase/7/docs/technotes/guides/vm/enhancements-7.html

    大概意思是说在JDK7中,内部字符串不再分配在Java堆的永久代中,而是与应用程序创建的其他对象一起分配在Java堆的主要部分(称为年轻代和老年代)中。

        可见字符串常量池在JDK7之前是保存在永久代中的,在JDK7及之后,是保存在堆空间中。

        以上是从官方的文档中找到的证明。

        以下是通过代码的角度来证明字符串常量池的保存位置。

        大概证明思路是,固定堆空间、永久代或元空间的大小,然后不断的往字符串常量池中添加字符,直到空间被占用完,看报出的错误是什么。

  1. 创建一个简单的MyTest.java。在main方法里利用String类的intern()方法将字符串添加到常量池。

public class MyTest {

/**
 * JDK1.6/1.7 运行参数设置
 * -Xms9m -Xmx9m -XX:PermSize=9m -XX:MaxPermSize=9m -XX:-UseGCOverheadLimit
 *
 * JDK1.8 运行参数设置
 * -Xms9m -Xmx9m -XX:MetaspaceSize=9m -XX:MaxMetaspaceSize=9m -XX:-UseGCOverheadLimit
 *
 * -XX:-UseGCOverheadLimit 添加这个为了排除其他干扰,避免垃圾回收内存比例达不到预期值而报 java.lang.OutOfMemoryError: GC Overhead limit exceeded
 */

    public static void main(String[] args) {
        System.out.println("Hello");
        //使用list保持常量池引用,避免GC回收
        List list = new ArrayList();
        int i = 0;
        while (true){
            list.add(String.valueOf(i).intern());
            i ++;
        }
    }
}

2. 配置运行JVM参数,使用JDK6、JDK7、JDK8版本查看运行结果。JVM参数中固定了堆空间、永久代或元空间的大小。

        参数说明:

        -Xms:初始化堆空间大小

        -Xmx: 最大堆空间大小

        -XX:PermSize: 代初始永久代大小

        -XX:MaxPermSize:最大永久化大小

        -XX:MetaspaceSize:初始化元空间大小

        -XX:MaxMetaspaceSize:最大元空间大小                       

  • JDK6运行,报了 java.lang.OutOfMemoryError: PermGen space 的错误,可见JDK6字符串常量池是保存在永久代中。

 

  •  JDK7、JDK8运行,都报了 java.lang.OutOfMemoryError: Java heap space 的错误,可见JDK7、JDK8字符串常量池是保存在堆空间中。

 

    以上从代码角度证明了,java字符串常量池在JDK7之前是保存在永久代中的,在JDK7及之后,是保存在堆空间中。

    好了,本次的分享到此结束,以后要是再有人让你证明Java字符串常量池保存在哪里,不至于一脸懵逼了,至少可以把我的文章甩给他看。


    关注我,不定时更新分享更多程序员务实的知识!转载请标明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值