Q:强引用、软引用、弱引用和幻象引用有什么区别?
在Java中,除了原始数据类型的变量,其他都是所谓的引用类型,指向不同的对象。理解引用对掌握JAVA对象生命周期和JVM内部机制很有帮助。
不同的引用类型,体现的是对象不同的可达性,和对垃圾收集的影响。
强引用
所谓强引用,就是最常见的普通对象引用。主要有强引用指向一个对象,就表明对象还活着。垃圾收集器就不会碰这种对象。
当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
软引用
软引用,可以让对象豁免一些垃圾收集,只有当JVM觉得内存不足时,才会试图回收软引用指向的对象。JVM会确保在抛出OOM异常前,清理软引用指向的对象。软引用通常用来实现内存敏感的缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用。如果软引用所引用对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中。
也就是说,垃圾收集线程会在虚拟机抛出OutOfMemoryError之前回收软引用对象,而且虚拟机会尽可能优先回收长时间闲置不用的软引用对象。对那些刚构建的或刚使用过的"较新的"软对象会被虚拟机尽可能保留,这就是引入引用队列ReferenceQueue的原因。
弱引用
弱引用并不能让对象豁免垃圾收集,仅仅是提供一种访问弱引用状态下对象的途径。用来构建一种没有特定约束的关系,比如维护一种非强制性的映射关系。它同样是很多缓存实现的选择。
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
幻象引用
幻象引用,也称虚引用,你不能通过它来访问对象。它只是提供了一种确保对象被finalize之后,做某些事的机制。比如用来作为post-mortem清理或是进行监控对象的创建和销毁。虚引用主要用来跟踪对象被垃圾回收器回收的活动。
虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
Java不同的可达性
- 强可达。当一个对象有一个或多个线程可以不通过引用访问到的情况。如,我们新创建一个对象,那么创建它的线程对它就是强可达。
- 软可达。我们只能通过软引用才能访问到对象的状态。
- 弱可达。
- 幻象可达。
- 不可达
判断对象的可达性,是JVM垃圾级收集器决定如何处理对象的一部分考虑。
所有的引用类型都是java.lang.ref.Reference的子类,它提供了get方法。除了幻象引用,如果对象还没有被销毁,都可以用get方法获取原有对象。也就是软可达和弱可达可以重新变为强可达。
引用队列
网友评论