JVM工作原理与实战(二十三):堆的垃圾回收-引用计数法和可达性分析法

简介: JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了判断堆上的对象是否可以回收的方法(引用计数法、可达性分析法)、查看垃圾回收日志等内容。

一、判断堆上的对象是否可以回收

在垃圾回收过程中,首要任务是判断哪些对象可以安全地回收。常见的判断方法主要有两种:引用计数法可达性分析法

1.引用计数法

引用计数法是一种直观且简单的垃圾回收策略。每个对象都持有一个引用计数器,当一个对象被引用时,其计数器加1;当引用被解除时,计数器减1。当计数器归0时,对象即被认为是可以回收的。

image.gif

引用计数法的优点在于其实现简单,对于某些特定场景(如C++中的智能指针)非常适用。然而,它也存在一些明显的缺点:

  • 每次引用或取消引用都需要更新计数器,这可能对系统性能产生影响。尤其是在对象引用频繁增减的情况下,这可能导致大量的更新操作,从而影响程序的运行效率。
  • 引用计数法无法处理循环引用的情况。例如,当对象A引用对象B,同时对象B也引用对象A时,即使这两个对象之间没有其他外部引用,它们的引用计数也不会归0,从而导致无法正常回收,造成内存泄漏。

2.可达性分析算法

相比之下,可达性分析算法更为复杂,但它能够解决循环引用问题。在可达性分析中,所有对象被分为两类:垃圾回收的根对象(GC Root)和普通对象。这些根对象通常是程序中可以直接访问的对象。算法通过追踪从根对象到目标对象的引用链,来判断一个对象是否可达。如果一个对象从任何根对象都无法达到,那么这个对象就被认为是不可达的,可以被安全地回收。

案例:

在图中,A对象引用了B对象,B对象又引用了C和D对象,从而形成了一个引用链。可达性分析算法的核心思想在于,如果一个对象无法从垃圾回收的根对象(GC Root)可达,那么这个对象就可以被安全地回收。反之,如果一个对象可以从某个GC Root对象可达,那么这个对象就被认为是活动的,不可被回收。

image.gif

在Java中,就采用了可达性分析算法来判定对象是否可以回收。所有的根对象都存在于线程的栈中或者其他一些固定区域(例如JDK中的强引用、软引用、弱引用、虚引用)。如果一个对象被根对象直接或间接引用,那么这个对象就被认为是活动的、不可被回收的;反之,如果一个对象没有任何根对象引用它,那么这个对象就可以被垃圾回收。

可达性分析算法的主要优点是它可以处理复杂的引用关系和避免循环引用的问题。然而,它也有一些缺点:

  • 可达性分析算法需要追踪和记录所有的引用关系,这可能会增加内存和CPU的使用。
  • 如果一个程序在运行过程中改变了引用关系(例如在Java中的null指针异常),这可能会影响到垃圾回收的结果。
  • 对于一些动态生成的对象或者短生命周期的对象,可达性分析可能无法有效地判定其是否可以回收。

GC Root对象:

在垃圾回收过程中,GC Root对象是指垃圾回收的起始点。这些对象是可达的,并且通过引用关系可以访问到堆上的其他对象。常见的GC Root对象包括:

  • 线程Thread对象:每个线程在Java虚拟机中都有一个对应的Thread对象,这些对象引用线程栈帧中的方法参数、局部变量等,为垃圾回收提供了可达性路径。
  • 系统类加载器加载的java.lang.Class对象:系统类加载器加载的java.lang.Class对象,这些对象引用类中的静态变量。
  • 监视器对象:当一个线程执行同步代码块或同步方法时,会创建一个监视器对象来保存同步锁的信息。
  • 本地方法调用时使用的全局对象:在使用本地方法(native method)时,Java虚拟机可能会创建一些全局对象。

二、查看垃圾回收日志

要获取垃圾回收的详细信息,可以使用-verbose:gc参数。该参数提供了关于垃圾回收操作的详细日志输出。

-verbose:gc

image.gif

通过使用此参数,可以获取有关垃圾回收的详细信息,包括每次垃圾回收的类型、回收前和回收后的内存使用情况等,这些信息对于分析和优化垃圾回收性能非常有用。

image.gif


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了判断堆上的对象是否可以回收的方法(引用计数法、可达性分析法)、查看垃圾回收日志等内容,希望对大家有所帮助。

相关文章
|
3月前
|
监控 Java
压力测试Jmeter的简单使用,性能监控-堆内存与垃圾回收 -jvisualvm的使用
这篇文章介绍了如何使用JMeter进行压力测试,包括测试前的配置、测试执行和结果查看。同时,还探讨了性能监控工具jconsole和jvisualvm的使用,特别是jvisualvm,它可以监控内存泄露、跟踪垃圾回收、执行时内存和CPU分析以及线程分析等,文章还提供了使用这些工具的详细步骤和说明。
压力测试Jmeter的简单使用,性能监控-堆内存与垃圾回收 -jvisualvm的使用
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
60 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
28天前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。
|
1月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
48 2
|
1月前
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
58 0
|
4月前
|
Java
Jinfo 查看 jvm 配置及使用 Jstat 查看堆内存使用与垃圾回收
Jinfo 查看 jvm 配置及使用 Jstat 查看堆内存使用与垃圾回收
139 5
|
4月前
|
运维 监控 Java
(十)JVM成神路之线上故障排查、性能监控工具分析及各线上问题排错实战
经过前述九章的JVM知识学习后,咱们对于JVM的整体知识体系已经有了全面的认知。但前面的章节中,更多的是停留在理论上进行阐述,而本章节中则更多的会分析JVM的实战操作。
107 1
|
4月前
|
缓存 监控 Java
Java虚拟机(JVM)性能调优实战指南
在追求软件开发卓越的征途中,Java虚拟机(JVM)性能调优是一个不可或缺的环节。本文将通过具体的数据和案例,深入探讨JVM性能调优的理论基础与实践技巧,旨在为广大Java开发者提供一套系统化的性能优化方案。文章首先剖析了JVM内存管理机制的工作原理,然后通过对比分析不同垃圾收集器的适用场景及性能表现,为读者揭示了选择合适垃圾回收策略的数据支持。接下来,结合线程管理和JIT编译优化等高级话题,文章详细阐述了如何利用现代JVM提供的丰富工具进行问题诊断和性能监控。最后,通过实际案例分析,展示了性能调优过程中可能遇到的挑战及应对策略,确保读者能够将理论运用于实践,有效提升Java应用的性能。 【
201 10
|
3月前
|
存储 监控 算法
深入解析JVM内部结构及GC机制的实战应用
深入解析JVM内部结构及GC机制的实战应用
|
1月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
37 4