JVM工作原理与实战(二十四):堆的垃圾回收-对象引用

简介: JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了强引用、软引用、弱引用、虚引用、终结器引用等内容。

在Java中,对象的生命周期由垃圾回收器管理。在可达性算法中,描述的对象引用通常指的是强引用,即GCRoot对象对普通对象有引用关系,只要这层关系存在,普通对象就不会被回收。但除了强引用外,Java还设计了其他几种引用方式,以应对不同的内存管理需求。

一、软引用

1.软引用的执行过程

软引用是一种相对较弱的引用关系。如果一个对象仅被软引用关联,当内存不足时,这些数据将会被虚拟机视为垃圾回收的候选对象。在JDK 1.2之后,通过SoftReference类实现了软引用。它常被用于缓存的实现。例如,当内存不足时,虚拟机首先尝试回收软引用关联的对象。如果仍不能解决内存问题,软引用中的对象将被回收。如果仍然内存不足,将抛出OutOfMemory异常。

案例:

根对象(GC Root)到目标对象(对象A)形成了引用链,对象A不可回收:

image.gif

根对象(GC Root)到目标对象(对象A)没有形成引用链,该对象被认为是不可达的,可以被安全地回收。当内存不足时,软引用中的对象(对象A)将被回收:

image.gif

软引用的执行过程如下:

  1. 将对象使用软引用包装起来,如new SoftReference<对象类型>(对象)。
  2. 当内存不足时,虚拟机尝试进行垃圾回收。
  3. 如果垃圾回收仍不能解决内存不足的问题,回收软引用中的对象。
  4. 如果依然内存不足,抛出OutOfMemory异常。

案例:

将100M的数据放入软引用中:

byte[] bytes = new byte[1024 *1024 *100];
    SoftReference<byte[]> softReference = new SoftReference<byte[]>(bytes);
image.gif

2.SoftReference队列机制

在内存不足的情况下,如果软引用所指向的对象被回收,那么SoftReference对象本身也需要被回收。为了解决这个问题,SoftReference提供了一套有效的队列机制,以确保可以准确判断哪些SoftReference对象需要被回收。这套机制使得SoftReference能够与垃圾回收器协同工作,从而优化内存管理。

SoftReference队列机制:

  • 创建与引用队列的关联:在创建SoftReference对象时,通过特定的构造器可以传入一个引用队列。这个队列用于存储SoftReference对象,以便后续的管理和回收。
  • 对象回收与队列更新:当软引用包含的对象被标记为可回收时,该软引用对象会被自动加入到指定的引用队列中。这一步骤确保了被回收对象的跟踪和管理。
  • 强引用删除:为了进一步管理内存,程序需要遍历这些引用队列,并删除SoftReference的强引用。这一操作是为了确保软引用对象不再占用额外的内存空间,从而使其可以被垃圾回收器顺利回收。

这套队列机制确保了内存管理的效率和准确性,使SoftReference能够适应不同的内存需求,有效地管理Java虚拟机的内存资源。

二、弱引用

弱引用的工作原理与软引用在很多方面是相似的,但在垃圾回收方面存在显著差异。主要区别在于,当弱引用关联的对象被垃圾回收时,不论当前系统内存空间足够与否,都会被回收。这一特性使得弱引用在处理内存管理时更为直接和高效。

在JDK 1.2版本之后,Java引入了WeakReference类来实现弱引用机制。这一设计使得弱引用主要在ThreadLocal中得到应用,为其提供了更为灵活和有效的内存管理方案。同时,弱引用对象同样可以利用引用队列进行回收。这一机制确保了垃圾回收器能够跟踪并管理弱引用对象的生命周期,从而更有效地释放内存空间。

image.gif

案例:

将100M的数据放入弱引用中:

byte[] bytes = new byte[1024 *1024 *100];
    WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes);
image.gif

三、虚引用与终结器引用

在Java的内存管理中,虚引用和终结器引用是两种较为特殊的引用类型,它们在常规开发中的使用频率相对较低。

1.虚引用

虚引用,也被称为幽灵引用或幻影引用,是一种抽象的引用关系。通过虚引用来获取一个对象是不可能的,因为虚引用仅仅提供了对对象的一个弱化形式的引用关系。其主要用途在于跟踪对象被垃圾回收的行为。当一个对象仅持有虚引用时,它就像没有任何引用一样,随时可能被垃圾回收器回收。

在Java中,PhantomReference类代表了虚引用。它允许程序监控对象何时被垃圾回收,并在回收时收到通知。这在某些场景下是有用的,例如管理外部资源或实现特定的内存管理策略。

2.终结器引用

终结器引用与对象的finalize方法相关联。当一个对象需要被回收时,终结器引用会将其关联到Finalizer类中的一个引用队列中。随后,FinalizerThread线程会从队列中取出对象并执行其finalize方法。需要注意的是,finalize方法的执行是在垃圾回收之后进行的,因此,当对象第二次被回收时,它才真正被回收。

尽管在finalize方法中可以将对象重新使用强引用关联上,但这通常是不推荐的。因为这可能导致内存泄漏或其他不可预见的问题。开发者应该谨慎处理终结器引用的使用,并确保finalize方法在执行完毕后不再保持对对象的引用。


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了强引用、软引用、弱引用、虚引用、终结器引用等内容,希望对大家有所帮助。

相关文章
|
24天前
|
监控 算法 Java
Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
30 0
|
22小时前
|
算法 网络协议 Java
【JVM】——GC垃圾回收机制(图解通俗易懂)
GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)
|
23天前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
3天前
|
缓存 Java
JVM对象引用
本次课程聚焦JVM对象引用,涵盖强引用、软引用、弱引用和虚引用。强引用是最常见的引用类型,确保对象不会被垃圾回收器回收,适用于需要确保对象存活的场景;软引用在内存不足时会被优先回收,常用于缓存;弱引用的对象随时可能被回收,适合临时对象;虚引用最弱,主要用于接收对象回收通知,进行资源清理。通过合理选择引用类型,可优化内存管理,避免内存泄露。
|
1月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
276 1
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
44 4
|
21天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
22小时前
|
存储 Java 程序员
【JVM】——JVM运行机制、类加载机制、内存划分
JVM运行机制,堆栈,程序计数器,元数据区,JVM加载机制,双亲委派模型
|
1月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
1月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
22 3