- 强引用:就是最常见的引用,通过等号赋值就是强引用。
- 软引用:当内存不足时自动释放引用。一般应用于需要大量内存的缓存程序中。
- 弱引用:不阻止垃圾回收,当强引用或者软引用都消失时,即使存在弱引用内存也会被释放。
- 幽灵引用:只引用一个对象的“灵魂”,幽灵引用是不能直接访问的,所以get方法永远返回null。这种引用能阻止JVM释放对象的内存,但是被引用的对象可以finalize。这东西有什么用呢?按照文档中的说法就是用于调整对象之间finalize的顺序。Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
下面通过代码展现他们之间的不同点。
幽灵引用
为了测试被引用的对象是否存在,只能通过全局的内存使用情况。实验结果是幽灵引用确实能阻止内存被回收,但是finalize在回收的时候才被调用,与文档描述不符。下面请看代码示例:import java.lang.ref.*; import java.util.*; public class Test { public static void main(String[] argv) { // 查看内存 // 实验结果是1M printMemory(); // 创建一个非常大的对象,便于查看内存使用率,构建一个幽灵引用 Object phantomObj = new BigObject(); ReferenceQueue refQ = new ReferenceQueue(); PhantomReference phantomRef = new PhantomReference(phantomObj, refQ); // 查看内存 // 实验结果是101M,说明创建的对象大小是100M printMemory(); // 释放强引用,执行内存回收 // 期望的输出结果应该是BigObject is finalized,实际结果是Phantom released。说明在只有幽灵引用的情况下finalize没有被调用,与文档描述不符。 phantomObj = null; sleep(); System.gc();System.gc();System.gc(); System.out.println("Phantom released"); // 查看内存 // 实验结果是101M,说明内存没有被回收 printMemory(); // 释放幽灵引用,执行内存回收、 phantomRef = null; refQ = null; // 实验证明:这句话如果没有那么内存不会被释放 sleep(); // 实验证明:如果没有这句话,输出结果呈现随机性,有时候内存没有回收 System.gc();System.gc();System.gc(); // 等内存被回收之后,再查看内存 // 实验结果是1M,说明内存已经被回收了 printMemory(); } private static void printMemory() { System.out.print("The memory usage is: "); System.out.println((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024.0/1024.0 + "MB"); } private static void sleep() { try { Thread.sleep(100); } catch(InterruptedException ex) { } } }
弱引用
下面请看代码示例:// 构建一个弱引用 String weakObj = new String("Weak Object"); ReferenceQueue weakQueue = new ReferenceQueue(); WeakReference weakReference = new WeakReference(weakObj, weakQueue); System.out.println("Weak Reference: " + weakReference.get()); // 清空强引用,并执行垃圾回收 weakObj = null; System.gc(); System.gc(); System.gc(); // 检测弱引用是否可用 // 实验结果:输出结果是null,说明已经被垃圾回收了。 System.out.println("Weak Reference: " + weakReference.get());
软引用
下面请看代码示例:// 构建一个软引用 String softObj = new String("Soft Object"); ReferenceQueue softQueue = new ReferenceQueue(); SoftReference softRef = new SoftReference(softObj, softQueue); System.out.println("Soft Reference: " + softRef.get()); // 清空强引用,并执行垃圾回收 softObj = null; System.gc(); System.gc(); System.gc(); // 检测软引用是否可用 // 输出结果是Soft Object,说明垃圾回收并没有回收软引用。 System.out.println("Soft Reference: " + softRef.get()); // 申请大量内存,直到内存不足 LinkedList li = new LinkedList(); while(true) { try { li.add(new Object[100000]); } catch(OutOfMemoryError e) { break; } } li = null; // 检测软引用是否可用 // 实验结果:输出null,说明在内存不足之后软引用已经被系统清理了。 System.out.println("Soft Reference: " + softRef.get());
Java中PhantomReference、WeakReference、SoftReference有什么区别?,布布扣,bubuko.com