深入理解 Java String#intern() 内存模型

canca8年前 (2016-03-30)Java技术272

字符串常量池是一个固定大小的HashMap,桶的数量默认是1009, Java7u40开始,该默认值增大到60013。在Java6当中,字符串常量池是放在Perm空间的,从Java7开始,字符串常量池被移到Heap空间。下面,我们通过测试程序来窥探字符串常量池在Java6Java7两个不同版本底下的内存分配情况。

测试程序

public class StringPoolTest { 

 

    public void testStringPoolWithLongString(){ 

        long i=0

        while(true){ 

            String longString = "This is a very long string, very very long string to test the gc behavior of the string constant pool"+i; 

            longString.intern(); 

            i++; 

        } 

    } 

 

    public static void main(String[] args){ 

        StringPoolTest stringPoolTest = new StringPoolTest(); 

        stringPoolTest.testStringPoolWithLongString(); 

    } 


测试程序很简单,一个死循环,循环里面通过递增变量i制造唯一的字符串,然后用main函数启动程序。

Java 6

我们使用版本Jdk1.6.0_29来跑该程序,打开Java VisualVM监控,可以看到,Perm区不断发生GC,由此的出结论,虽然字符串常量池放在Perm空间,但当Perm空间接近满的时候,JVM会将字符串常量池中的无用字符串回收掉。

深入理解 Java Stringintern() 内存模型 - Mr.Can - Mr.Cans Blog

 

Java 7

下面,我们切换到Jdk1.7.0_67重跑该程序,可以看到 Perm 区内存分配曲线很平滑,没有出现内存分配的现象。

深入理解 Java Stringintern() 内存模型 - Mr.Can - Mr.Cans Blog

 

但在Heap空间,新的对象不断产生,然后不断触发GC

深入理解 Java Stringintern() 内存模型 - Mr.Can - Mr.Cans Blog

 

结论

由于Perm区大小是有限的,通常只有几十MB,所以不推荐在Java6下广泛使用String.intern(),这篇文章string-intern-in-java-6-7-8的性能测试表明,在Java6底下大量使用intern()会导致应用性能的显著下降,还有可能产生OOM错误。但从Java7开始,字符串常量池被移到了Heap空间,Heap空间的大小只受制于机器的真实内存大小,因此,在Java7下使用String.intern()能更有效地减少重复String对象对内存的占用。

相关文章

对象序列化与反序列化

    序列化,并不是JAVA独有的。因此,在这里我用比较通俗的话说了。序列化就是把一个对象转换成有规则的二进制流。而反序列化就是把有规则的二进制数据重整成一个...

Socket与ServerSocket的问题

//服务器端:import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;imp...

Java语言的反射机制

    由于项目的需要,在项目中要实现即插即用的方式,也就是说可以动态地加载包,不用设置CLASSPATH路径。当项目发布时,不可能要用户来设置环境变量吧!因此,就要用到...

JAVA获得一个文件夹大小

在JAVA里没有现成的方法获取一个文件夹的大小,那么我们可以用递归的方法,获取文件夹的大小。    import  java.util.*;  im...

JAVA内部类终极实例

最近心情不好,不想说太多东西了!电脑坏了,我现在又病了. class ClassFactory{ private final static String userName = "Hello,...

过滤网页HTML标记

JAVA过滤HTML中的所有标记。非常好用!! package canca.regex; import java.util.regex.Matcher;import java.util.regex.P...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。