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

开发 后端
大家知道,Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,就会在字符串常量池中创建该字符串然后再返回。

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

测试程序

  1. public class StringPoolTest { 
  2.  
  3.     public void testStringPoolWithLongString(){ 
  4.         long i=0
  5.         while(true){ 
  6.             String longString = "This is a very long string, very very long string to test the gc behavior of the string constant pool"+i; 
  7.             longString.intern(); 
  8.             i++; 
  9.         } 
  10.     } 
  11.  
  12.     public static void main(String[] args){ 
  13.         StringPoolTest stringPoolTest = new StringPoolTest(); 
  14.         stringPoolTest.testStringPoolWithLongString(); 
  15.     } 

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

Java 6

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

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

Java 7

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

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

 

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

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

结论

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

责任编辑:王雪燕 来源: Code Log
相关推荐

2023-11-05 12:05:35

JVM内存

2022-06-22 08:02:11

CPU操作系统Java

2023-09-19 22:47:39

Java内存

2023-10-27 07:47:58

Java语言顺序性

2020-11-11 08:45:48

Java

2022-07-06 08:05:52

Java对象JVM

2021-09-08 17:42:45

JVM内存模型

2020-06-01 21:07:33

C11C++11内存

2013-06-20 10:25:56

2020-11-04 15:35:13

Golang内存程序员

2017-12-18 16:33:55

多线程对象模型

2021-11-26 00:00:48

JVM内存区域

2023-10-27 07:47:37

计算机内存模型

2015-12-28 11:41:57

JVM内存区域内存溢出

2016-12-08 15:36:59

HashMap数据结构hash函数

2020-07-21 08:26:08

SpringSecurity过滤器

2010-06-01 15:25:27

JavaCLASSPATH

2022-08-21 16:52:27

Linux虚拟内存

2009-06-19 14:10:42

Java多态性

2019-06-25 10:32:19

UDP编程通信
点赞
收藏

51CTO技术栈公众号