java intern

JDK7 中将StringPool从永久代移动到了老生代,并且可以通过-XX:StringTableSize=99991来改变常量池的大小。

public void equalTest(){
       String s = new String("1").intern();
       String s2 = "1";
       System.out.println(s2 == s);
   }
output: true

public void equalTest(){
       String s = new String("1");
       s.intern();
       String s2 = "1";
       System.out.println(s2 == s);
   }
output: false

jdk7下面第一段代码打印的是true,第二段打印的是false.
这是因为将常量池从永久的移动到老生代之后,intern()的意思是将该变量放到常量池中,因为new String("1")已经是在堆中了,所以会直接将其引用放入常量池中,这样当s2="1"语句直接去常量池中查找对象时得到的其实就是s所指向的对象。
第二段代码中,new String("1); 会生成两个对象一个是s指向的Object String,一个是常量池中的对象; 然后执行s.intern()的时候发现常量池中已经有该对象了,所以什么也不做。s2则指向常量池中的对象。因此s != s2

我们再来看下面这段代码:

public static void main(String[] args){
        int length = 100000000;
        String[] s = new String[length];
        int i = 0;
        while(i < length){
            s[i++] = new String("hellosdfasfsdddddddddddddd").intern();
        }
    }

new String("hellosdfasfsdddddddddddddd").intern() 这句话的意思是在常量池中new一个对象,所以当我们第一次执行常量池中有了这个对象之后,后面就不会再new新对象了,大大节约了内存空间。
下面是有intern和没有intern的堆内存使用情况,大家感受一下

s[i++] = new String("hellosdfasfsdddddddddddddd").intern();

PS Old Generation
   capacity = 1431830528 (1365.5MB)
   used     = 400008208 (381.47755432128906MB)
   free     = 1031822320 (984.0224456787109MB)
   27.936840301815383% used

s[i++] = new String("hellosdfasfsdddddddddddddd");

PS Old Generation
   capacity = 1431830528 (1365.5MB)
   used     = 1431412656 (1365.1014862060547MB)
   free     = 417872 (0.3985137939453125MB)
   99.97081554053861% used

你可能感兴趣的:(java intern)