您现在的位置是:主页 > news > 橡胶塑料制品公司网站建设/网站开发的流程

橡胶塑料制品公司网站建设/网站开发的流程

admin2025/6/14 7:44:55news

简介橡胶塑料制品公司网站建设,网站开发的流程,开发定制软件开发,广州市红十字会医院网站建设项目前言 字符串常量池在java6之前位于永久代,永久代从名字上已经告诉我们这里垃圾回收效果很差,如果字符串常量池中含有大量的字符串,那么很容易造成永久代溢出。从java7开始,字符串常量池挪到了堆中,堆空间一般比较大&a…

橡胶塑料制品公司网站建设,网站开发的流程,开发定制软件开发,广州市红十字会医院网站建设项目前言 字符串常量池在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