Java垃圾回收的工作原理和最佳做法

举报
_陈哈哈 发表于 2022/01/21 22:58:13 2022/01/21
【摘要】 在本文中,我们将研究Java垃圾回收,它的工作方式以及重要性。 Java垃圾回收的定义 Java垃圾回收是Java程序执行自动内存管理的过程。Java程序编译为字节码,可以在Java虚拟机(简称JVM)上运行。当Java程序在JVM上运行时,将在堆上创建对象,这是专用于该程序的内存的一部分。最终,将不再需要某些对象。垃圾收集器找...

在本文中,我们将研究Java垃圾回收,它的工作方式以及重要性。

Java垃圾回收的定义

Java垃圾回收是Java程序执行自动内存管理的过程。Java程序编译为字节码,可以在Java虚拟机(简称JVM)上运行。当Java程序在JVM上运行时,将在堆上创建对象,这是专用于该程序的内存的一部分。最终,将不再需要某些对象。垃圾收集器找到这些未使用的对象并将其删除以释放内存。

Java垃圾回收如何工作

Java垃圾收集是一个自动过程。程序员不需要显式标记要删除的对象。垃圾回收实现位于JVM中。每个JVM都可以实现垃圾回收,但是它很高兴。唯一的要求是它符合JVM规范。尽管有许多JVM,但Oracle的HotSpot是迄今为止最常见的。它提供了一套强大而成熟的垃圾收集选项。

尽管HotSpot具有针对各种用例进行了优化的多个垃圾收集器,但其所有垃圾收集器都遵循相同的基本过程。第一步,识别未引用的对象并将其标记为可进行垃圾回收。第二步,删除标记的对象。(可选)可以在垃圾回收器删除对象之后压缩内存,以便剩余的对象在堆开始时位于连续的块中。压缩过程使在分配给现有对象的内存块之后更容易按顺序将内存分配给新对象。

HotSpot的所有垃圾收集器都实现了按年龄分类对象的分代垃圾收集策略。世代垃圾收集背后的基本原理是,大多数对象都是短暂的,并且在创建后不久就可以进行垃圾收集了。

 

            

                                                                               

堆分为三个部分:

  • 年轻一代:新创建的对象始于年轻一代。年轻一代又细分为Eden空间和所有Survivor空间,在Eden空间中所有新对象都开始运行,在其中一个垃圾收集周期结束后,对象从Eden中移出。当从Young Generation收集对象时,这是次要的垃圾收集事件。
  • 老一代:寿命长的对象最终从年轻一代迁移到老一代。从上一代垃圾回收对象时,这是一个重要的垃圾回收事件。
  • 永久生成:元数据(例如类和方法)存储在永久生成中。不再使用的类可能是从永久代收集的垃圾。

在完全垃圾收集事件期间,所有代中未使用的对象将被垃圾收集。

HotSpot有四个垃圾收集器:

  • 串行:所有垃圾回收事件都在一个线程中串行进行。在每个垃圾回收之后执行压缩。
  • 并行:多个线程用于次要垃圾回收。单线程用于大型垃圾回收和旧式压缩。另外,Parallel Old变量使用多个线程进行主要垃圾收集和Old Generation压缩。
  • CMS(并发标记扫描):使用与并行相同的算法,多个线程用于次要垃圾回收。大型垃圾收集是多线程的,例如Parallel Old,但是CMS与应用程序进程同时运行,以最大程度地减少“停止世界”事件(即,当垃圾收集器正在运行时停止应用程序)。不执行压缩。
  • G1(垃圾优先):最新的垃圾收集器旨在替代CMS。它像CMS一样是并行和并发的,但是与较旧的垃圾收集器相比,它的工作原理却大相径庭。

Java垃圾收集的好处

Java垃圾收集的最大好处是,它可以自动处理未使用的对象或无法访问的对象的删除, 以释放重要的内存资源。使用无垃圾收集的语言(例如C和C ++)工作的程序员必须在其代码中实现手动内存管理。

尽管需要额外的工作,但一些程序员还是主张手动内存管理胜于垃圾回收,这主要是出于控制和性能方面的考虑。尽管有关内存管理方法的争论仍在继续,但垃圾收集现在已成为许多流行编程语言的标准组成部分。对于垃圾收集器会对性能产生负面影响的方案,Java提供了许多选项来调整垃圾收集器以提高其效率。

Java垃圾收集最佳实践

对于许多简单的应用程序,Java垃圾回收不是程序员需要自觉考虑的事情。但是,对于希望提高Java技能的程序员来说,了解Java垃圾回收的工作方式以及如何对其进行调整非常重要。

除了垃圾收集的基本机制外,了解Java中垃圾收集的最重要要点之一是它不是确定性的,无法预测运行时何时进行垃圾收集。可以在代码中包含一个提示,以使用System.gc()或Runtime.gc()方法运行垃圾收集器,但它们不能保证垃圾收集器会真正运行。

调整Java垃圾收集的最佳方法是在JVM上设置标志。标志可以调整要使用的垃圾收集器(例如,Serial,G1等),堆的初始和最大大小,堆段的大小(例如,Young Generation,Old Generation)等等。被调整的应用程序的性质是很好的设置初始指南。例如,并行垃圾收集器效率很高,但经常会导致“世界停止”事件,使其更适合后端处理,在这种情况下可以长时间停顿垃圾收集。

另一方面,CMS垃圾收集器旨在最大程度地减少暂停,使其非常适合响应性很重要的GUI应用程序。可以通过更改堆或堆的大小并使用jstat之类的工具测量垃圾收集效率来完成其他微调。

文章来源: chensj.blog.csdn.net,作者:_陈哈哈,版权归原作者所有,如需转载,请联系作者。

原文链接:chensj.blog.csdn.net/article/details/104457216

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。