@c102zkl
2018-08-03T07:18:22.000000Z
字数 2298
阅读 550
Java小知识
Java从JDK1.2版本开始,把对象的引用分为四种级别:强引用、软引用、弱引用 、虚引用。
强引用:使用最普遍的引用,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,也不会回收强引用对象。
软引用:如果一个对象只具有软引用,内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
弱引用:发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
虚引用:不会决定对象的生命周期。如果一个对象仅持有虚引用,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用必须和引用队列(ReferenceQueue)联合使用。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以内存被回收之前采取必要的行动。
Java中提供这四种引用类型主要有两个目的:
第一是可以让程序员通过代码的方式决定某些对象的生命周期;
第二是有利于JVM进行垃圾回收。
在java.lang.ref包中提供了三个类:SoftReference类、WeakReference类和PhantomReference类,他们分别对应软引用、弱引用和虚引用。这是三个类的父类都是Reference类,他们的方法基本上都一样,我们以SoftReference为例:
public class SoftReference<T> extends Reference<T> {
private T referent; /* Treated specially by GC */
// 构造方法1,生成指向referent对象的软引用
public SoftReference(T referent)
// 构造方法2,生成指向referent对象的软引用,并将这个软引用和引用队列q绑定在一起
public SoftReference(T referent, ReferenceQueue<? super T> q)
// 通过get方法得到,软引用所指向的对象
public T get()
}
SoftReference类从父类Reference中继承了一个referent变量,这个变量就是专门用来存储软引用所指向对象的,下面的例子中会讲到
如果这个引用指向的对象已经被回收,那么get( )将返回null
还有一个ReferenceQueue类这就是上面提到的引用队列,:它可以和上面三个类联合使用,以便跟踪JVM中所回收的对象的活动。
public class ReferenceQueue<T> {
public Reference<? extends T> poll() //将队列顶端的元素抛出
public Reference<? extends T> remove() // 将队列元素删除
}
软引用(softReference)用来描述一些还有用但是并非必须的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。
SoftReference<T> sr = new SoftReference<T>(new Object());
软引用使用例子传送门:https://www.cnblogs.com/mjorcen/p/3968018.html
弱引用(WeakReference),一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。Java源码中的java.util.WeakHashMap中的key就是使用弱引用,我的理解就是,一旦我不需要某个引用,JVM会自动帮我处理它,这样我就不需要做其它操作。
WeakReference<T> wrf = new WeakReference<T>(new Object());
弱引用使用例子传送门:http://www.importnew.com/21206.html
虚引用(PhantomReference),虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入ReferenceQueue中。注意,其它引用是被JVM回收后才被传入ReferenceQueue中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有ReferenceQueue,使用例子:
PhantomReference<T> prf = new PhantomReference<T>(new Object(), new ReferenceQueue<>());
对象销毁前的一些操作,比如说资源释放等。Object.finalize()虽然也可以做这类动作,但是这个方式即不安全又低效(传送门:http://blog.csdn.net/aitangyong/article/details/39450341),so。