WeakReference与SoftReference

本文通过两个测试程序详细解析Java中的WeakReference和SoftReference的区别与应用场景,揭示它们如何影响垃圾回收策略。

WeakReference与SoftReference都可以用来保存对象的实例引用,这两个类与垃圾回收有关。

WeakReference是弱引用,其中保存的对象实例可以被GC回收掉。这个类通常用于在某处保存对象引用,而又不干扰该对象被GC回收,通常用于Debug、内存监视工具等程序中。因为这类程序一般要求即要观察到对象,又不能影响该对象正常的GC过程。

最近在JDK的Proxy类的实现代码中也发现了Weakrefrence的应用,Proxy会把动态生成的Class实例暂存于一个由Weakrefrence构成的Map中作为Cache。

SoftReference是强引用,它保存的对象实例,除非JVM即将OutOfMemory,否则不会被GC回收。这个特性使得它特别适合设计对象Cache。对于Cache,我们希望被缓存的对象最好始终常驻内存,但是如果JVM内存吃紧,为了不发生OutOfMemoryError导致系统崩溃,必要的时候也允许JVM回收Cache的内存,待后续合适的时机再把数据重新Load到Cache中。这样可以系统设计得更具弹性。

WeakReference的一个测试程序

import java.lang.ref.WeakReference;

public class WeakReferenceTest {

/**
 * @param args
 */
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!");
}

} 运行结果: 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的一个测试程序: import java.lang.ref.SoftReference;

public class SoftReferenceTest {

/**
 * @param args
 */
public static void main(String[] args) {
    A a = new A();
    a.str = "Hello, reference";
    SoftReference<A> sr = new SoftReference<A>(a);
    a = null;
    int i = 0;
    while (sr.get() != null) {
        System.out.println(String.format("Get str from object of SoftReference: %s, count: %d", sr.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!");
}

}

程序运行结果:

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

Get str from object of SoftReference: Hello, reference, count: 13

Get str from object of SoftReference: Hello, reference, count: 14

Get str from object of SoftReference: Hello, reference, count: 15

Get str from object of SoftReference: Hello, reference, count: 16

Get str from object of SoftReference: Hello, reference, count: 17

Get str from object of SoftReference: Hello, reference, count: 18

Get str from object of SoftReference: Hello, reference, count: 19

Get str from object of SoftReference: Hello, reference, count: 20

System.gc() was invoked!

Get str from object of SoftReference: Hello, reference, count: 21

Get str from object of SoftReference: Hello, reference, count: 22

Get str from object of SoftReference: Hello, reference, count: 23

Get str from object of SoftReference: Hello, reference, count: 24

Get str from object of SoftReference: Hello, reference, count: 25

Get str from object of SoftReference: Hello, reference, count: 26

Get str from object of SoftReference: Hello, reference, count: 27

Get str from object of SoftReference: Hello, reference, count: 28

上面的打印结果会一直持续下去。 因为soft.get()一直不会为空 SoftReference比WeakReference生命力更强,当JVM的内存不吃紧时,即使引用的对象被置为空了,Soft还可以保留对该对象的引用,此时的JVM内存池实际上还保有原来对象,只有当内存吃紧的情况下JVM才会清除Soft的引用对象,并且会在未来重新加载该引用的对象。

而WeakReference则当清理内存池时会自动清理掉引用的对象。

转载于:https://my.oschina.net/mtk/blog/101792

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值