先知
- Java中除了八大基本数据类型,其他都是引用类型,指向各种不同的对象。
- java.lang.ref包下提供了引用对象类(共包括五个类:PhantomReference、Reference、ReferenceQueue、SoftReference、WeakReference),支持在某种程度上与垃圾回收器GC(垃圾回收机制回收某个对象主要是看是否有引用指向这个对象)之间的交互。
- 对象分类:强可达对象、软可达对象、弱可达对象、虚可达对象、不可达对象
强可达对象:如果某一线程可以不必遍历所有引用对象而直接到达一个对象,则该对象是强可达对象。新创建的对象对于创建它的线程而言是强可达对象。
软可达对象:如果一个对象不是强可达对象,但通过遍历某一软引用可以到达它,则该对象是软可达对象。
弱可达对象:如果一个对象既不是强可达对象,也不是软可达对象,但通过遍历弱引用可以到达它,则该对象是弱可达对象。当清除对某一弱可到达对象的弱引用时,便可以终止此对象了。
虚可达对象:如果一个对象既不是强可达对象,也不是软可达对象或弱可达对象,它已经终止,并且某个虚引用在引用它,则该对象是虚可达对象。
不可达对象:最后,当不能以上述任何方法到达某一对象时,该对象是不可达对象,因此可以回收此对象。
Java的引用
如上所知,Java中把对象的引用分成了四个级别,分别为:强引用 、软引用、弱引用、虚引用。
而Java中提供这四种引用类型主要有两个目的:划分对象不同的可达性和GC对对象回收的影响。
强引用
- 强引用:是指创建一个对象并把这个对象赋给一个引用变量。
- 表现:Object object =new Object();
- 特点:只要强引用存在,GC永远不会回收该对象。JVM内存空间不足时,它宁愿抛出OutOfMemory错误,也不会回收该对象。如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,就可以根据具体的垃圾回收机制被回收。
软引用
- 软引用:SoftReference,如果一个对象具有软引用,内存空间足够时,GC就不会回收它。
- 特点:
- SoftReference保存对一个Java对象的软引用,该软引用的存在不妨碍GC对该对象的回收。也就是说,在GC对这个对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用;一旦GC回收该对象之后,get()方法将返回null。
- 软引用对象最常用于实现内存敏感的缓存,比如图片缓存。
- 使用软引用能防止MemoryLeak,增强程序的健壮性。
弱引用
- 弱引用:WeakReference,弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象(前提是只被弱引用,没有其他强引用等)。
- 举例:为什么Android自定义内部类AsyncTask要使用WeakReference?
- 因为内部类MyAsyncTask会隐式持有外部类Activity,当结束Activity时MyAsyncTask持有的Activity是弱引用,那么Activity能被正常GC,不会引发内存泄漏。
虚引用
- 虚引用:PhantomReference,最弱的一种引用关系,如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被GC回收。
- 为了确保可回收的对象仍然保持原状,虚引用的指示对象不能被获取,即虚引用的get方法总是返回 null。虚引用唯一目的是能在这个对象被GC回收时收到一个系统通知。
表格对比
引用类型 | GC回收时机 | 用途 |
---|---|---|
强引用 | 不回收 | 最常使用 |
软引用 | 内存不足时回收 | 缓存、防止内存泄漏等 |
弱引用 | 每次GC时回收 | 缓存、防止内存泄漏等 |
虚引用 | 随时可能被回收 | 在对象被GC回收时收到一个系统通知 |
总结
总的来说,强引用是我们最常使用的,而对于其他三种类型的引用,使用得最多的就是软引用和弱引用。这两种既有相似之处又有区别,它们都是用来描述非必需对象的,但是被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在每次GC时会被回收。