Java强引用、软引用、弱引用、幻象引用详解

原贴地址:http://www.appcnd.com/blog/articles/90.html

在Java中,除了原始数据类型的变量,其他所有都属于引用类型、指向各种不同的对象。

引用包含4种不同的类型:强引用、软引用、弱引用、幻象引用;不同的引用类型,主要体现的是对象不同的可达性状态和对垃圾回收的影响。

强引用

强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

软引用

软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。

弱引用

弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。

幻象引用

和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与幻象引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。幻象引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有幻象引用,就会把这个幻象引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了幻象引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个幻象引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

 

验证

设置堆大小(新生代≈10M,老年代≈10M)

1

-Xms20m -Xmx20m -XX:NewRatio=1

 

MyObj:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public class MyObj {

     

    public MyObj() {

        System.out.println("对象" this "创建");

    }

     

    /**

     * 重写finalize方法,在对象被gc的时候打印日志

     * @throws Throwable

     */

    @Override

    protected void finalize() throws Throwable {

        super.finalize();

        System.out.println(this " is gc");

    }

 

}

1、强引用

1.1 

1

2

3

4

5

6

@Test

public void test01() {

    MyObj obj = new MyObj();

    // new一个20M的byte数组,使堆空间不足,进而触发gc

    byte[] bytes = new byte[1024 1024 20];

}

1

2

对象com.test.MyObj@4e9ba398创建

java.lang.OutOfMemoryError: Java heap space

分析:对于强引用对象,即使堆空间不足的时候也不会被垃圾回收。

1.2 

1

2

3

4

5

6

7

@Test

public void test01() {

    MyObj obj = new MyObj();

    obj = null;

    // new一个20M的byte数组,使堆空间不足,进而触发gc

    byte[] bytes = new byte[1024 1024 20];

}

1

2

3

对象com.test.MyObj@4e9ba398创建

com.test.MyObj@4e9ba398 is gc

java.lang.OutOfMemoryError: Java heap space

分析:将强引用置为null后,gc的时候才会被回收。

2、软引用

2.1 

1

2

3

4

5

6

7

8

@Test

public void test01() {

    SoftReference<MyObj> softReference = new SoftReference<MyObj>(new MyObj());

    System.out.println("堆空间充足的时候主动触发gc");

    System.gc();

    System.out.println("new一个20M的byte数组,使堆空间不足,进而触发gc");

    byte[] bytes = new byte[1024 1024 20];

}

1

2

3

4

5

对象com.test.MyObj@4e9ba398创建

堆空间充足的时候主动触发gc

new一个20M的byte数组,使堆空间不足,进而触发gc

com.test.MyObj@4e9ba398 is gc

java.lang.OutOfMemoryError: Java heap space

分析:可以明显看到在堆空间充足的时候,jvm不会回收软引用对象,软引用对象只有在堆空间不足的时候才会被回收。

2.2 结合ReferenceQueue使用

1

2

3

4

ReferenceQueue<MyObj> queue = new ReferenceQueue();

MyObj obj = new MyObj();

// 在obj被jvm回收的时候,相应的reference对象(softReference)会被放到queue里

SoftReference<MyObj> softReference = new SoftReference<MyObj>(obj, queue);

3、弱引用

1

2

3

4

5

6

@Test

public void test01() {

    WeakReference<MyObj> weakReference = new WeakReference<MyObj>(new MyObj());

    System.out.println("堆空间充足的时候主动触发gc");

    System.gc();

}

1

2

3

对象com.test.MyObj@4e9ba398创建

堆空间充足的时候主动触发gc

com.test.MyObj@4e9ba398 is gc

1

2

3

4

5

6

@Test

public void test01() {

    WeakReference<MyObj> weakReference = new WeakReference<MyObj>(new MyObj());

    System.out.println("new一个20M的byte数组,使堆空间不足,进而触发gc");

    byte[] bytes = new byte[1024 1024 20];

}

1

2

3

4

对象com.test.MyObj@4e9ba398创建

new一个20M的byte数组,使堆空间不足,进而触发gc

com.test.MyObj@4e9ba398 is gc

java.lang.OutOfMemoryError: Java heap space

分析:对于弱引用对象,无论堆内存是否充足,只要发生gc,弱引用对象都会被回收。

弱引用也可以结合ReferenceQueue来使用,在弱引用对象被回收的时候,其对应的reference对象会被放入queue中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值