JVM 垃圾回收的工作原理

admin 2022年6月29日17:18:54安全开发评论2 views3224字阅读10分44秒阅读模式
 
JVM 垃圾回收的工作原理
导读:对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 是如何处理程序中的变量和类实例的。
本文字数:3434,阅读时长大约:5分钟

对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 是如何处理程序中的变量和类实例的。

Java 之所以能够如此流行,自动 垃圾回收(Garbage Collection)(GC)功不可没,它也是 Java 最重要的几个特性之一。在这篇文章中,我将说明为什么垃圾回收如此重要。本文的主要内容为:自动的分代垃圾回收、JVM 划分内存的依据,以及 JVM 垃圾回收的工作原理。

JVM 垃圾回收的工作原理

Java 内存分配

Java 程序的内存空间被划分为以下四个区域:

1. 堆区(Heap):对象实例就是在这个区域分配的。不过,当我们声明一个对象时,堆中不会发生任何内存分配,只是在栈中创建了一个对象的引用而已。
2. 栈区(Stack):方法、局部变量和类的实例变量就是在这个区域分配的。
3. 代码区(Code):这个区域存放了程序的字节码。
4. 静态区(Static):这个区域存放了程序的静态数据和静态方法。

JVM 垃圾回收的工作原理

什么是自动垃圾回收?

自动垃圾回收是这样一个过程:首先,堆中的所有对象会被分类为“被引用的”和“未被引用的”;接着,“未被引用的对象”就会被做上标记,以待之后删除。其中,“被引用的对象”是指程序中的某一部分仍在使用的对象,“未被引用的对象”是指目前没有正在被使用的对象。

许多编程语言,例如 C 和 C++,都需要程序员手动管理内存的分配和释放。在 Java 中,这一过程是通过垃圾回收机制来自动完成的(尽管你也可以在代码中调用 system.gc(); 来手动触发垃圾回收)。

垃圾回收的基本步骤如下:

JVM 垃圾回收的工作原理

1、标记已使用和未使用的对象

在这一步骤中,已使用和未使用的对象会被分别做上标记。这是一个及其耗时的过程,因为需要扫描内存中的所有对象,才能够确定它们是否正在被使用。

JVM 垃圾回收的工作原理

标记已使用和未使用的对象

JVM 垃圾回收的工作原理

2、扫描/删除对象

有两种不同的扫描和删除算法:

简单删除(标记清除):它的过程很简单,我们只需要删除未被引用的对象即可。但是,后续给新对象分配内存就会变得很困难了,因为可用空间被分割成了一块块碎片。

JVM 垃圾回收的工作原理

标记清除的过程

删除压缩(标记整理):除了会删除未被引用的对象,我们还会压缩被引用的对象(未被删除的对象)。这样以来,新对象的内存分配就相对容易了,并且内存分配的效率也有了提升。

JVM 垃圾回收的工作原理

标记整理的过程

JVM 垃圾回收的工作原理

什么是分代垃圾回收,为什么需要它?

正如我们在“扫描删除”模型中所看到的,一旦对象不断增长,我们就很难扫描所有未使用的对象以回收内存。不过,有一项实验性研究指出,在程序执行期间创建的大多数对象,它们的存活时间都很短。

既然大多数对象的存活时间都很短,那么我们就可以利用这个事实,从而提升垃圾回收的效率。该怎么做呢?首先,JVM 将内存划分为不同的“代”。接着,它将所有的对象都分类到这些内存“代”中,然后对这些“代”分别执行垃圾回收。这就是“分代垃圾回收”。

JVM 垃圾回收的工作原理

堆内存的“代”和分代垃圾回收过程

为了提升垃圾回收中的“标记清除”的效率,JVM 将对内存划分成以下三个“代”:

◈ 新生代(Young Generation)
◈ 老年代(Old Generation)
◈ 永久代(Permanent Generation)

JVM 垃圾回收的工作原理

Hotspot 堆内存结构

下面我将介绍每个“代”及其主要特征。

JVM 垃圾回收的工作原理

新生代

所有创建不久的对象都存放在这里。新生代被进一步分为以下两个区域:

1. 伊甸区(Eden):所有新创建的对象都在此处分配内存。
2. 幸存者区(Survivor),分为 S0 和 S1:经历过一次垃圾回收后,仍然存活的对象会被移动到两个幸存者区中的一个。

JVM 垃圾回收的工作原理

对象分配

在新生代发生的分代垃圾回收被称为 “次要回收(Minor GC)” (LCTT 译注:也称为“新生代回收(Young GC)”)。Minor GC 过程中的每个阶段都是“停止世界(Stop The World)” (STW)的,这会导致其他应用程序暂停运行,直到垃圾回收结束。这也是次要回收更快的原因。

一句话总结:伊甸区存放了所有新创建的对象,当它的可用空间被耗尽,第一次垃圾回收就会被触发。

JVM 垃圾回收的工作原理

填充伊甸区

次要回收:在该垃圾回收过程中,所有存活和死亡的对象都会被做上标记。其中,存活对象会被移动到 S0 幸存者区。当所有存活对象都被移动到了 S0,未被引用的对象就会被删除。

JVM 垃圾回收的工作原理

拷贝被引用的对象

S0 中的对象年龄为 1,因为它们挺过了一次次要回收。此时,伊甸区和 S1 都是空的。

每当完成清理后,伊甸区就会再次接受新的存活对象。随着时间的推移,伊甸区和 S0 中的某些对象被宣判死亡(不再被引用),并且伊甸区的可用空间也再次耗尽(填满了),那么次要回收 又将再次被触发。

JVM 垃圾回收的工作原理

对象年龄增长

这一次,伊甸区和 S0 中的死亡和存活的对象会被做上标记。其中,伊甸区的存活对象会被移动到 S1,并且年龄增加至 1。S0 中的存活对象也会被移动到 S1,并且年龄增加至 2(因为它们挺过了两次次要回收)。此时,伊甸区和 S0 又是空的了。每次次要回收之后,伊甸区和两个幸存者区中的一个都会是空的。

新对象总是在伊甸区被创建,周而复始。当下一次垃圾回收发生时,伊甸区和 S1 都会被清理,它们中的存活对象会被移动到 S0 区。每次次要回收之后,这两个幸存者区(S0 和 S1)就会交换一次。

JVM 垃圾回收的工作原理

额外年龄增长

这个过程会一直进行下去,直到某个存活对象的年龄达到了某个阈值,然后它就会被移动到一个叫做“老年代”的地方,这是通过一个叫做“晋升”的过程来完成的。

使用 -Xmn 选项可以设置新生代的大小。

JVM 垃圾回收的工作原理

老年代

这个区域存放着那些挺过了许多次次要回收,并且达到了某个年龄阈值的对象。

JVM 垃圾回收的工作原理

晋升

在上面这个示例图表中,晋升的年龄阈值为 8。在老年代发生的垃圾回收被称为 “主要回收(Major GC)”。(LCTT 译注:也被称为“全回收(Full GC)”)

使用 -Xms 和 -Xmx 选项可以分别设置堆内存大小的初始值和最大值。(LCTT 译注:结合上面的 -Xmn 选项,就可以间接设置老年代的大小了。)

JVM 垃圾回收的工作原理

永久代

永久代存放着一些元数据,它们与应用程序、Java 标准环境以及 JVM 自用的库类及其方法相关。JVM 会在运行时,用到了什么类和方法,就会填充相应的数据。当 JVM 发现有未使用的类,就会卸载或是回收它们,从而为正在使用的类腾出空间。

使用 -XX:PermGen 和 -XX:MaxPerGen 选项可以分别设置永久代大小的初始值和最大值。

JVM 垃圾回收的工作原理

元空间

Java 8 引入了元空间(Metaspace),并用它替换了永久代。这么做的好处是自动调整大小,避免了 内存不足(OutOfMemory)(OOM)错误。

JVM 垃圾回收的工作原理

总结

本文讨论了各种不同的 JVM 内存“代”,以及它们是如何在分代垃圾回收算法中起作用的。对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 处理程序中的变量和类实例的方式。这种理解使你能够规划和排除代码故障,并理解特定平台固有的潜在限制。

正文配图来自:Jayashree Huttanagoudar,CC BY-SA 4.0


via: https://opensource.com/article/22/6/garbage-collection-java-virtual-machine

作者:Jayashree Huttanagoudar 选题:lkxed 译者:lkxed 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

JVM 垃圾回收的工作原理
LCTT 译者 :六开箱
🌟🌟🌟🌟🌟
JVM 垃圾回收的工作原理
翻译: 83.0 篇

|

贡献: 98 天
2022-03-16
2022-06-22
https://linux.cn/lctt/lkxed
欢迎遵照 CC-BY-SA 协议规定转载,
如需转载,请在文章下留言 “转载:公众号名称”,
我们将为您添加白名单,授权“转载文章时可以修改”。

原文始发于微信公众号(Linux中国):JVM 垃圾回收的工作原理 | Linux 中国

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月29日17:18:54
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  JVM 垃圾回收的工作原理 http://cn-sec.com/archives/1140342.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: