在Java中内存管理,引用分为四大类,强引用HardReference、弱引用WeakReference、软引用SoftReference和虚引用PhantomReference
强引用HardReference:
HardReference对象是即使虚拟机内存吃紧抛出OOM也不会导致这一引用的对象被回收
弱引用WeakReference:
最容易被垃圾回收。GC发生时即被回收。
通常用于在某处保存对象引用,而又不干扰该对象被GC回收,通常用于Debug、内存监视工具等程序中。因为这类程序一般要求即要观察到对象,又不能影响该对象正常的GC过程。更适合于一些数量不多,但体积稍微庞大的对象。
public class WeakReferenceTest {
public static void main(String[] args) {
A a = new A();
a.str = "Hello, reference";
WeakReference<A> weak = new WeakReference<A>(a);
a = null;
int i = 0;
while (weak.get() != null) {
System.out
.println(String.format("Get str from object of WeakReference: %s, count: %d", weak.get().str, ++i));
if (i % 10 == 0) {
System.gc();
System.out.println("System.gc() was invoked!");
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
System.out.println("object a was cleared by JVM!");
}
}
result:
Get str from object of WeakReference: Hello, reference, count: 1
Get str from object of WeakReference: Hello, reference, count: 2
Get str from object of WeakReference: Hello, reference, count: 3
Get str from object of WeakReference: Hello, reference, count: 4
Get str from object of WeakReference: Hello, reference, count: 5
Get str from object of WeakReference: Hello, reference, count: 6
Get str from object of WeakReference: Hello, reference, count: 7
Get str from object of WeakReference: Hello, reference, count: 8
Get str from object of WeakReference: Hello, reference, count: 9
Get str from object of WeakReference: Hello, reference, count: 10
System.gc() was invoked!
object a was cleared by JVM!
软引用SoftReference:
使用SoftReference来解决内存不至于快速回收,同时当内存短缺面临Java VM崩溃抛出OOM前时,软引用将会强制回收内存。它保存的对象实例,除非JVM即将OutOfMemory,否则不会被GC回收。这个特性使得它特别适合设计对象Cache。在内存宽松的情况下,即使执行gc操作,也不会被回收。
public class SoftReferenceTest {
public static void main(String[] args) {
A a = new A();
a.str = "Hello, reference";
SoftReference<A> weak = new SoftReference<A>(a);
a = null;
int i = 0;
while (weak.get() != null) {
System.out
.println(String.format("Get str from object of SoftReference: %s, count: %d", weak.get().str, ++i));
if (i % 10 == 0) {
System.gc();
System.out.println("System.gc() was invoked!");
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
System.out.println("object a was cleared by JVM!");
}
}
result:
Get str from object of SoftReference: Hello, reference, count: 1
Get str from object of SoftReference: Hello, reference, count: 2
Get str from object of SoftReference: Hello, reference, count: 3
Get str from object of SoftReference: Hello, reference, count: 4
Get str from object of SoftReference: Hello, reference, count: 5
Get str from object of SoftReference: Hello, reference, count: 6
Get str from object of SoftReference: Hello, reference, count: 7
Get str from object of SoftReference: Hello, reference, count: 8
Get str from object of SoftReference: Hello, reference, count: 9
Get str from object of SoftReference: Hello, reference, count: 10
System.gc() was invoked!
Get str from object of SoftReference: Hello, reference, count: 11
Get str from object of SoftReference: Hello, reference, count: 12
如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?
不会立即释放对象占用的内存。如果对象的引用被置为null,只是断开了当前线程栈帧中对该对象的引用关系,而垃圾收集器是运行在后台的线程,只有当用户线程运行到安全点(safe point)或者安全区域才会扫描对象引用关系,扫描到对象没有被引用则会标记对象,这时候仍然不会立即释放该对象内存,因为有些对象是可恢复的(在finalize方法中恢复引用)。只有确定了对象无法恢复引用的时候才会清除对象内存。
虚引用PhantomReference:
虚引用一般没有实际意义,仅仅观察GC的活动状态,对于测试比较实用同时必须和ReferenceQueue一起使用。