您现在的位置是:主页 > news > 橡胶塑料制品公司网站建设/网站开发的流程
橡胶塑料制品公司网站建设/网站开发的流程
admin2025/6/14 7:44:55【news】
简介橡胶塑料制品公司网站建设,网站开发的流程,开发定制软件开发,广州市红十字会医院网站建设项目前言 字符串常量池在java6之前位于永久代,永久代从名字上已经告诉我们这里垃圾回收效果很差,如果字符串常量池中含有大量的字符串,那么很容易造成永久代溢出。从java7开始,字符串常量池挪到了堆中,堆空间一般比较大&a…
前言
字符串常量池在java6之前位于永久代,永久代从名字上已经告诉我们这里垃圾回收效果很差,如果字符串常量池中含有大量的字符串,那么很容易造成永久代溢出。从java7开始,字符串常量池挪到了堆中,堆空间一般比较大,而且堆空间的回收效率很高,所以相对于在永久代,放到堆空间后,内存溢出的情况大大减少。
本文接下来先通过代码观察一下常量池,然后介绍字符串常量池如何实现的。本文使用的是jdk8。
本文目录
- 一、代码实验
- 二、字符串常量池实现原理
一、代码实验
这里主要使用String.intern方法,intern()方法的作用是如果字符串不在常量池中,则将该字符串的引用放入常量池,并将引用返回,如果在常量池中,则将常量池中字符串的引用返回。
public static void main(String[] args){String s1=new String("hello");[1]String s2=s1.intern();[2]System.out.println(s1==s2);//falseSystem.out.println(s1=="hello");//falseSystem.out.println(s2=="hello");//trueString s3=new StringBuilder().append(s1).append(s2).toString();[3]String s4=s3.intern();[4]System.out.println(s3==s4);//trueSystem.out.println(s3=="hellohello");//true}
运行结果:
false
false
true
true
true
代码[1]处因为hello是一个字面常量,所以java会将字符串hello放入常量池一份,同时在堆中创建一个String对象,这两个对象是不同的,而且字符串常量池中已经有了字符串hello,所以代码[2]处直接返回常量池的引用,因此也就出现了下面打印的false、false、true。
代码[3]处会在堆中创建一个字符串对象hellohello,该字符串此时在常量池中不存在,然后代码[4]处将堆中的引用放入到常量池中,并返回该引用,因此s3等于s4。接下来的字面常量hellohello其实就是代码[4]放入字符串常量池中的引用,因此执行也是true。
下面我写了一段代码来验证字符串常量池挪到了堆区中。
public static void main(String[] args)throws Exception{String name = ManagementFactory.getRuntimeMXBean().getName();System.out.println(name);String pid = name.split("@")[0];System.out.println("Pid is:" + pid); //打印PIDThread.sleep(2000); //为了更好的观察现象//s1和s2都是很长的字符串String s1 = "qqq。。。";String s2 = "qqqw。。。。";System.out.print(s1.length());System.gc();s1 = null;s2 = null;Thread.sleep(2000); //为了更好的观察现象System.gc();Thread.sleep(2000); //为了更好的观察现象System.gc();Thread.sleep(2000); //为了更好的观察现象
}
下面是运行jstat命令的结果:
PS C:\Program Files\Java\jdk1.8.0_161\bin> .\jstat.exe -gc 16524 1sS0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
13312.0 13312.0 0.0 0.0 82432.0 11578.1 218624.0 0.0 4480.0 781.6 384.0 75.9 0 0.000 0 0.000 0.000
13312.0 13312.0 0.0 0.0 82432.0 1648.7 218624.0 1872.3 4864.0 3635.7 512.0 382.9 1 0.002 1 0.009 0.011
13312.0 13312.0 0.0 0.0 82432.0 1648.7 218624.0 1512.4 4864.0 3641.2 512.0 382.9 2 0.003 2 0.022 0.025
13312.0 13312.0 0.0 0.0 82432.0 0.0 218624.0 1508.7 4864.0 3641.3 512.0 382.9 3 0.004 3 0.042 0.046
一共进行了三次垃圾回收,从结果上可以很明显的看出,老年代(OU)和新生代(EU)的总大小在减少。上面的结果可以说明字符串常量池中的字符串和普通对象一样,初始位于新生代,随着代数的增加,会被挪到老年代中。
二、字符串常量池实现原理
字符串常量池使用哈希表来存储字符串,类似于HashMap,初始桶的个数是60013(可以使用-XX:+PrintStringTableStatistics在程序退出时打印结果可以看到桶的个数),如果存储的字符串非常多,可以使用-XX:StringTableSize增大桶个数,以减少冲突。
参考文章
https://blog.csdn.net/weixin_38308374/article/details/110674739