java中的弱引用和字符串常量池
WeakReference作为java中弱引用的关键字,在执行System.gc();之后,它所指向的对象会被GC回收。先看下面的代码:
public class WeakRef {
public static void main(String[] args) throws InterruptedException {
WeakReference r = new WeakReference(new String("I'm here"));
WeakReference sr = new WeakReference("I'm here nihao");
System.out.println("before gc: r=" + r.get() + ", static=" + sr.get());
System.gc();
Thread.sleep(100);
// only r.get() becomes null
System.out.println("after gc: r=" + r.get() + ", static=" + sr.get());
}
}
上面代码的运行结果是
before gc: r=I’m here, static=I’m here nihao
after gc: r=null, static=I’m here nihao
那么我们很奇怪为什么sr没有被GC回收呢?在参考了Java字符常量池和weakreference string didnt garbage collected之后。经过代码测试得到如下的结果:
1 在创建String对象时可以用两种方式
String s = new String("I am here");
String ss = "I am here";
2 String s = new String(“I am here”) 创建了几个对象?
答:
2个
解析:
首先,出现了字面量”I am here”,那么去String Pool中查找是否有相同字符串存在,因为程序就这一行代码所以肯定没有,那么就在Java Heap中用字面量”I am here”首先创建1个String对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量s。
接着,new String(“I am here”),关键字new又在Java Heap中创建了1个对象,然后调用接收String参数的构造器进行了初始化。最终s的引用是这个String对象
如上:2个
3
String abc = new String ("test string pool");
String abcd = "test string pool";
boolean flag = abc==abcd;
System.out.println("compare :"+ flag);
得到的结果是
compare :false
第一句执行:首先,出现了字面量”test string pool”,那么去String Pool中查找是否有相同字符串存在,因为程序就这一行代码所以肯定没有,那么就在Java Heap中用字面量”test string pool”首先创建1个String对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量s。
字符串常量池中存放的时引用还是对象,这个问题是最常见的。字符串常量池存放的是对象引用,不是对象。在Java中,对象都创建在堆内存中。
接着,new String(“test string pool”),关键字new又在Java Heap中创建了1个对象,然后调用接收String参数的构造器进行了初始化。最终s的引用是这个String对象。
第二句执行:String Pool中查找是否有相同字符串存在,则返回了这个对象的引用给abcd。(这里的对象是第一句执行过程中创建的第一个对象)
下图反应了执行这几句过程中JVM的情况。
再回到开始的问题,r所指向的内存空间,只有r一个变量指向,而sr则有两个变量指向它,一个是sr,一个是string pool中对它引用。所以执行System.gc后,r被回收,而sr指向的内存空间有一个隐形的强引用,不被回收。
第一次写技术博客,有理解不到位的地方大家多多指点。