你们知道,Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,若是字符串不存在,就会在字符串常量池中建立该字符串而后再返回。java
字符串常量池是一个固定大小的HashMap,桶的数量默认是1009, 从Java7u40开始,该默认值增大到60013。在Java6当中,字符串常量池是放在Perm空间的,从Java7开始,字符串常量池被移到Heap空间。下面,咱们经过测试程序来窥探字符串常量池在Java6,Java7两个不一样版本底下的内存分配状况。函数
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函数启动程序。性能
咱们使用版本Jdk1.6.0_29来跑该程序,打开Java VisualVM监控,能够看到,Perm区不断发生GC,由此的出结论,虽然字符串常量池放在Perm空间,但当Perm空间接近满的时候,JVM会将字符串常量池中的无用字符串回收掉。测试
下面,咱们切换到Jdk1.7.0_67重跑该程序,能够看到Perm区内存分配曲线很平滑,没有出现内存分配的现象。spa
但在Heap空间,新的对象不断产生,而后不断触发GCcode
因为Perm区大小是有限的,一般只有几十MB,因此不推荐在Java6下普遍使用String.intern(),这篇文章string-intern-in-java-6-7-8的性能测试代表,在Java6底下大量使用intern()会致使应用性能的显著降低,还有可能产生OOM错误。但从Java7开始,字符串常量池被移到了Heap空间,Heap空间的大小只受制于机器的真实内存大小,所以,在Java7下使用String.intern()能更有效地减小重复String对象对内存的占用。orm