自从jdk 1.2 开始, Java的引用类型分就为四种, 强引用Strong reference, 软引用Soft reference, 弱引用weak reference,虚引用 phantom reference。Reference 是一个抽象类,而 SoftReference,WeakReference,PhantomReference 以及 FinalReference 都是继承它的具体类。下面分析一下四种类型的特点及GC 是如何垃圾回收的
1.StrongReference
位于java.lang.ref 包下,这是使用最多的类型, 比如new 一个对象obj, 当我们在Heap中创建了对象obj, 这就是一个强引用类型对象。对于强引用对象, 垃圾回收器在进行垃圾回收时如果发现该对象没有被任何引用时才会回收,否则会一直在Heap中,对于jvm OOM(out of memory error), 一般都是因为太多的强引用类型的对象没有被回收导致内存溢出。
Object obj = new Object();
特点:
强引用可以直接访问目标对象。
强引用所指向的对象在任何时候都不会被系统回收。
强引用可能导致内存泄漏。
2.SoftReference
当JVM内存不够时,GC 才会回收只有SoftReference 引用的对象, 一般可用作缓存
Object obj = new Object(); SoftReference<Object> softReference = new SoftReference<Object>(obj);
或者
Object obj = new Object(); SoftReference<Object> softReference = new SoftReference<Object>(obj);
特点:
软引用使用 get() 方法取得对象的强引用从而访问目标对象。
软引用所指向的对象按照 JVM 的使用情况(Heap 内存是否临近阈值)来决定是否回收。
软引用可以避免 Heap 内存不足所导致的异常。
3.WeakReference
不管JVM 内存是否满, GC 都会回收只有WeakReference引用的对象
Object obj = new Object(); WeakReference<Object> weakReference = new WeakReference <Object>(obj);
或者
ReferenceQueue<Object> rq = new ReferenceQueue<Object>(); WeakReference <Object> weakReference = new WeakReference <Object>(obj, rq);
ReferenceQueue:主要是用来监听GC 对 reference对象的回收, 看下面的代码
private static class ReferenceHandler extends Thread { ReferenceHandler(ThreadGroup g, String name) { super(g, name); } public void run() { for (;;) { Reference r; synchronized (lock) { if (pending != null) { r = pending; Reference rn = r.next; pending = (rn == r) ? null : rn; r.next = r; } else { try { lock.wait(); } catch (InterruptedException x) { } continue; } } // Fast path for cleaners if (r instanceof Cleaner) { ((Cleaner)r).clean(); continue; } ReferenceQueue q = r.queue; if (q != ReferenceQueue.NULL) q.enqueue(r); } } } static { ThreadGroup tg = Thread.currentThread().getThreadGroup(); for (ThreadGroup tgn = tg; tgn != null; tg = tgn, tgn = tg.getParent()); Thread handler = new ReferenceHandler(tg, "Reference Handler"); /* If there were a special system-only priority greater than * MAX_PRIORITY, it would be used here */ handler.setPriority(Thread.MAX_PRIORITY); handler.setDaemon(true); handler.start(); }
pending是由jvm来赋值的,当Reference内部的referent对象的可达状态改变时,jvm会将Reference对象放入pending链表。一旦relevent= null,垃圾收集时会标记WeakReference的referent为不可达get()返回null,并且通过 赋值给pending ,触发ReferenceHandler线程处理pending。ReferenceHandler线程要做的是将pending对象enqueue,但默认我们所提供的queue,也就是从构造函数传入的是null,实际是使用了ReferenceQueue.NULL,Handler线程判断queue为ReferenceQueue.NULL则不进行操作,只有非ReferenceQueue.NULL 的queue才会将Reference进行enqueue。
当创建一个SoftReference/WeakReference对象后,会自动启动一个Demon thread, 该线程主要负责清理reference对象(对应于 private T referent;), 并将SoftReference/WeakReference对象放入ReferenceQueue。测试代码如下
public class ReferenceQueueTest { public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> rq = new ReferenceQueue<Object>(); WeakReference<Object> softReference = new WeakReference<Object>(obj, rq); System.out.println(softReference.get()); System.out.println(rq.poll()); obj=null; System.gc(); Thread.sleep(1000); System.out.println(softReference.get()); System.out.println(rq.poll()); } } 结果: java.lang.Object@de6ced null null java.lang.ref.WeakReference@14318bb
特点:
弱引用使用 get() 方法取得对象的强引用从而访问目标对象。
一旦系统内存回收,无论内存是否紧张,弱引用指向的对象都会被回收。
弱引用也可以避免 Heap 内存不足所导致的异常。
4.PhantomReference
虚引用是最弱的引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也不能通过get()方法来获得对象的引用,虚引用主要用来跟踪对象的垃圾回收
public class PhantomReference<T> extends Reference<T> { public T get() { return null; } public PhantomReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }
特点
虚引用永远无法使用 get() 方法取得对象的强引用从而访问目标对象。
虚引用所指向的对象在被系统内存回收前,虚引用自身会被放入 ReferenceQueue 对象中从而跟踪对象垃圾回收。
虚引用不会根据内存情况自动回收目标对象。
相关推荐
Your author likes to read reference manuals (believe it or not)—at least if they are reasonably complete—on the grounds that this is the most efficient way to absorb a language quickly.
Java in a Nutshell Java Language Reference Java AWT Reference Java Fundamental Classes Reference Exploring Java Combined Index Combined Search Web Version Credits
### Neo4j Java Reference 3.0:深入理解图数据库扩展与高级应用 #### 概述 《Neo4j Java Reference 3.0》是一本详细介绍如何使用Java语言来开发和扩展Neo4j图数据库的专业指南。本书不仅覆盖了Neo4j的核心功能,...
在Java编程语言中,`Reference`类是一个非常特殊且重要的概念,它超出了常规的引用类型,如`Object`或数组引用。`Reference`类及其子类主要用于处理对象的软引用、弱引用和虚引用,这些引用类型在内存管理,特别是...
Java reference sheet
Java: The Complete Reference, Eleventh Edition By 作者: Herbert Schildt ISBN-10 书号: 1260440230 ISBN-13 书号: 9781260440232 Edition 版本: 11 出版日期: 2018-12-12 pages 页数: (1955) The Definitive ...
Java The Complete Reference, 11th Edition 9781260440232 c.pdf Java The Complete Reference, 11th Edition 9781260440232 c.pdf Java The Complete Reference, 11th Edition 9781260440232 c.pdf
Java The Complete Reference 10th Edition Java9 编程官方参考(第10版) 带书签 文字版
Java Reference源码解析 Java Reference是Java语言的一种机制,用于追踪对象的可达性和垃圾回收。Java Reference源码解析主要为大家详细解析了Java Reference源码,具有一定的参考价值,感兴趣的小伙伴们可以参考...
在Neo4j-java-reference-3.3这份参考指南中,涵盖了多个关于如何在Java环境中使用和扩展Neo4j数据库的高级主题。文档内容涉及到如何嵌入Neo4j到Java应用中、使用Neo4j的遍历框架、手动索引、事务管理、在线备份以及...
Java自发布以来,已经经历了多个版本的迭代,目前最新的稳定版为Java 14,但本文档提及的《Java The Complete Reference 9th》涉及的Java版本是第九版对应的Java技术标准。 提到的《Java The Complete Reference 9...
### Java AWT(Abstract Window Toolkit)详解:掌握Java图形用户界面设计的核心技能 #### 引言:Java AWT——构建用户界面的基石 在Java的世界里,Abstract Window Toolkit(AWT)扮演着至关重要的角色,它为Java...
在Java编程语言中,"reference"是一个至关重要的概念,它涉及到对象的引用和内存管理。在Java的世界里,"Everything is Object",这意味着所有的数据都以对象的形式存在,而reference则是连接这些对象与程序代码的...
《Java The Complete Reference 第九版源代码》是一个深入学习Java编程语言的重要资源。这个压缩包包含的源代码是作者在书中讲解各种Java概念和技术时所使用的示例程序,旨在帮助读者更好地理解和应用Java编程知识。...
《neo4j-java-reference-3.1》是Neo4j官方发布的针对Java开发者的详细指南,旨在帮助开发者熟练地利用Java API与Neo4j图形数据库进行交互。这本书涵盖了从安装配置到高级特性的方方面面,是Java程序员在 Neo4j 领域...
Oracle8i Supplied Java Packages Reference Release 3 (8.1.7) 中的知识点 Oracle8i Supplied Java Packages Reference Release 3 (8.1.7) 是 Oracle 公司发布的一份关于 Java 包的参考手册。本手册的主要目的是...
《Java The Complete Reference》是Java编程领域的一本权威著作,其第八版主要涵盖了基于Java 7的全面知识。这本书详细解析了Java语言的各种特性和使用方法,为开发者提供了丰富的参考资料和实战指导。以下是对该书...