JAVA 各种Reference和垃圾回收机制

今天好好学习了一下java中的各种reference.一共分为以下几种:

1. 强引用
2. 软引用 SoftReference
3. 弱引用 WeakReference
4. 虚引用 PhantomReference
5. FinalReference 所有实现finalize()方法的对象

一下是Oracle JDK. IBM的JDK会有些不同。

** 强引用 ** :
String a = new String(“A”);

一般程序都在使用。申请太多时,会有OutOfMemory异常。gc不会自动释放。

** 软引用 ** :
SoftReference a = new SoftReference(new String(“A”));
String real = a.get(); // if memory is near/equal to threshold of memory, real may be null.

gc自动释放。不会有OutOfMemory异常,但是在垃圾回收之前/finalize()之前就会放入到引用队列 ReferenceQueue. 适合作为cache.

** 弱引用 ** :
WeakReference a = new WeakReference(new String(“A”));
String real = a.get(); // may null

gc自动释放。不会有OutOfMemory异常,但是在垃圾回收之前/finalize()之前就会放入到引用队列 ReferenceQueue. 适合作为Cache, 并且这里的意思为:如果能在内存中看到这个cache对象最好,看不到,load这个对象也不会损失很多效率。

** 虚引用 ** :
PhantomReference a = new PhantomReference(new String(“A”));
String real = a.get(); // is always null

gc不会自动释放, 会有OutOfMemory。对象在垃圾回收/finalize()之后才会放入到ReferenceQueue中。这里会保证对象不会再次引用。也可以用于判断该对象是否已经从内存中移除。

** FinalReference ** :
其实不能直接使用。这个的子类 Finalizer也不能直接使用。系统会在运行时启动FinalizerThread。这个Thread用于清理ReferenceQueue中的对象。首先调用该对象finalize()方法,然后将引用赋值为null. 这样就解除了引用和对象的关系。这里的ReferenceQueue可以看做是以上各个引用都被最终放入到的queue对象。因为所有对象都有finalize()方法。 另外垃圾回收有两步,第一步确定垃圾回收的对象,第二步调用finalize()方法,将对象从内存中移除。在finalize()方法调用前,强引用是可以召回对象,使对象不会移除内存。这样会导致垃圾回收会反反复复回收多次,仍未能将该对象移除。但是如果使用虚引用,就能确保,进入ReferenceQueue中的引用,其对象一定已经移除内存。

参考:
http://www.ibm.com/developerworks/cn/java/j-lo-langref/
https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
http://yangguangfu.iteye.com/blog/849317