From 65a3845dd3a22595a22e968fd86d9ac3ee50f493 Mon Sep 17 00:00:00 2001 From: Xingyu Wang Date: Wed, 22 Jun 2022 09:48:48 +0800 Subject: [PATCH] RP @lkxed https://linux.cn/article-14742-1.html --- ...ion works inside a Java Virtual Machine.md | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) rename {translated/tech => published}/20220607 How Garbage Collection works inside a Java Virtual Machine.md (68%) diff --git a/translated/tech/20220607 How Garbage Collection works inside a Java Virtual Machine.md b/published/20220607 How Garbage Collection works inside a Java Virtual Machine.md similarity index 68% rename from translated/tech/20220607 How Garbage Collection works inside a Java Virtual Machine.md rename to published/20220607 How Garbage Collection works inside a Java Virtual Machine.md index e102895b7c..cd4ed74084 100644 --- a/translated/tech/20220607 How Garbage Collection works inside a Java Virtual Machine.md +++ b/published/20220607 How Garbage Collection works inside a Java Virtual Machine.md @@ -3,17 +3,16 @@ [#]: author: "Jayashree Huttanagoudar https://opensource.com/users/jayashree-huttanagoudar" [#]: collector: "lkxed" [#]: translator: "lkxed" -[#]: reviewer: " " -[#]: publisher: " " -[#]: url: " " +[#]: reviewer: "wxy" +[#]: publisher: "wxy" +[#]: url: "https://linux.cn/article-14742-1.html" JVM 垃圾回收的工作原理 ====== -对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 是如何处理程序中的变量和类实例的。 -![咖啡豆][1] +![](https://img.linux.net.cn/data/attachment/album/202206/22/094238qvh45pv2jtpde9td.jpg) -图源:Pixabay. CC0. +> 对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 是如何处理程序中的变量和类实例的。 Java 之所以能够如此流行,自动 垃圾回收Garbage Collection(GC)功不可没,它也是 Java 最重要的几个特性之一。在这篇文章中,我将说明为什么垃圾回收如此重要。本文的主要内容为:自动的分代垃圾回收、JVM 划分内存的依据,以及 JVM 垃圾回收的工作原理。 @@ -21,10 +20,10 @@ Java 之所以能够如此流行,自动 垃圾回收Garbage Collecti Java 程序的内存空间被划分为以下四个区域: -1. 堆区(Heap):对象实例就是在这个区域分配的。不过,当我们声明一个对象时,堆中不会有任何内存分配发生,只是在栈中创建了一个对象的引用而已。 -2. 栈区(Stack):方法、局部变量和类的实例变量就是在这个区域分配的。 -3. 代码区(Code):这个区域存放了程序的字节码。 -4. 静态区(Static):这个区域存放了程序的静态数据和静态方法。 +1. 堆区Heap:对象实例就是在这个区域分配的。不过,当我们声明一个对象时,堆中不会发生任何内存分配,只是在栈中创建了一个对象的引用而已。 +2. 栈区Stack:方法、局部变量和类的实例变量就是在这个区域分配的。 +3. 代码区Code:这个区域存放了程序的字节码。 +4. 静态区Static:这个区域存放了程序的静态数据和静态方法。 ### 什么是自动垃圾回收? @@ -34,13 +33,13 @@ Java 程序的内存空间被划分为以下四个区域: 垃圾回收的基本步骤如下: -#### 1. 标记已使用和未使用的对象 +#### 1、标记已使用和未使用的对象 在这一步骤中,已使用和未使用的对象会被分别做上标记。这是一个及其耗时的过程,因为需要扫描内存中的所有对象,才能够确定它们是否正在被使用。 ![标记已使用和未使用的对象][2] -#### 2. 扫描/删除对象 +#### 2、扫描/删除对象 有两种不同的扫描和删除算法: @@ -62,56 +61,56 @@ Java 程序的内存空间被划分为以下四个区域: 为了提升垃圾回收中的“标记清除”的效率,JVM 将对内存划分成以下三个“代”: -* 年轻代 -* 老年代 -* 永久代 +* 新生代Young Generation +* 老年代Old Generation +* 永久代Permanent Generation ![Hotspot 堆内存结构][5] 下面我将介绍每个“代”及其主要特征。 -#### 年轻代 +#### 新生代 -所有创建不久的对象都存放在这里。年轻代被进一步分为以下两个区域: +所有创建不久的对象都存放在这里。新生代被进一步分为以下两个区域: -1. 伊甸区(Eden):所有新创建的对象都在此处分配内存。 -2. 幸存者区(Survivor,分为 S0 和 S1):经历过一次垃圾回收后,仍然存活的对象会被移动到两个幸存者区中的一个。 +1. 伊甸区Eden:所有新创建的对象都在此处分配内存。 +2. 幸存者区Survivor,分为 S0 和 S1:经历过一次垃圾回收后,仍然存活的对象会被移动到两个幸存者区中的一个。 ![对象分配][6] -在年轻代发生的分代垃圾回收被称为 “Minor GC”。Minor GC 过程中的每个阶段都是“停止世界Stop The World”(STW)的,这会导致其他应用程序暂停运行,直到垃圾回收结束。这也是 Minor GC 更快的原因。 +在新生代发生的分代垃圾回收被称为 “次要回收Minor GC”(LCTT 译注:也称为“新生代回收Young GC”)。Minor GC 过程中的每个阶段都是“停止世界Stop The World”(STW)的,这会导致其他应用程序暂停运行,直到垃圾回收结束。这也是次要回收更快的原因。 一句话总结:伊甸区存放了所有新创建的对象,当它的可用空间被耗尽,第一次垃圾回收就会被触发。 ![填充伊甸区][7] -Minor GC:在该垃圾回收过程中,所有存活和死亡的对象都会被做上标记。其中,存活对象会被移动到 S0 幸存者区。当所有存活对象都被移动到了 S0,未被引用的对象就会被删除。 +次要回收:在该垃圾回收过程中,所有存活和死亡的对象都会被做上标记。其中,存活对象会被移动到 S0 幸存者区。当所有存活对象都被移动到了 S0,未被引用的对象就会被删除。 ![拷贝被引用的对象][8] -S0 中的对象年龄为 1,因为它们挺过了一次 Minor GC。此时,伊甸区和 S1 都是空的。 +S0 中的对象年龄为 1,因为它们挺过了一次次要回收。此时,伊甸区和 S1 都是空的。 -每当完成清理后,伊甸区就会再次接受新的存活对象。随着时间的推移,伊甸区和 S0 中的某些对象被宣判死亡(不再被引用),并且伊甸区的可用空间也再次耗尽(填满了),那么 Minor GC 又将再次被触发。 +每当完成清理后,伊甸区就会再次接受新的存活对象。随着时间的推移,伊甸区和 S0 中的某些对象被宣判死亡(不再被引用),并且伊甸区的可用空间也再次耗尽(填满了),那么次要回收 又将再次被触发。 ![对象年龄增长][9] -这一次,伊甸区和 S0 中的死亡和存活的对象会被做上标记。其中,伊甸区的存活对象会被移动到 S1,并且年龄增加至 1。S0 中的存活对象也会被移动到 S1,并且年龄增加至 2(因为它们挺过了两次 Minor GC)。此时,伊甸区和 S0 又是空的了。每次 Minor GC 之后,伊甸区和两个幸存者区中的一个都会是空的。 +这一次,伊甸区和 S0 中的死亡和存活的对象会被做上标记。其中,伊甸区的存活对象会被移动到 S1,并且年龄增加至 1。S0 中的存活对象也会被移动到 S1,并且年龄增加至 2(因为它们挺过了两次次要回收)。此时,伊甸区和 S0 又是空的了。每次次要回收之后,伊甸区和两个幸存者区中的一个都会是空的。 -新对象总是在伊甸区被创建,周而复始。当下一次垃圾回收发生时,伊甸区和 S1 都会被清理,它们中的存活对象会被移动到 S0 区。每次 Minor GC 之后,这两个幸存者区(S0 和 S1)就会交换一次。 +新对象总是在伊甸区被创建,周而复始。当下一次垃圾回收发生时,伊甸区和 S1 都会被清理,它们中的存活对象会被移动到 S0 区。每次次要回收之后,这两个幸存者区(S0 和 S1)就会交换一次。 ![额外年龄增长][10] 这个过程会一直进行下去,直到某个存活对象的年龄达到了某个阈值,然后它就会被移动到一个叫做“老年代”的地方,这是通过一个叫做“晋升”的过程来完成的。 -使用 `-Xmn` 选项可以设置年轻代的大小。 +使用 `-Xmn` 选项可以设置新生代的大小。 ### 老年代 -这个区域存放着那些挺过了许多次 Minor GC,并且达到了某个年龄阈值的对象。 +这个区域存放着那些挺过了许多次次要回收,并且达到了某个年龄阈值的对象。 ![晋升][11] -在上面这个示例图表中,晋升的年龄阈值为 8。在老年代发生的垃圾回收被称为 “Major GC”。 +在上面这个示例图表中,晋升的年龄阈值为 8。在老年代发生的垃圾回收被称为 “主要回收Major GC”。(LCTT 译注:也被称为“全回收Full GC”) 使用 `-Xms` 和 `-Xmx` 选项可以分别设置堆内存大小的初始值和最大值。(LCTT 译注:结合上面的 `-Xmn` 选项,就可以间接设置老年代的大小了。) @@ -123,13 +122,13 @@ S0 中的对象年龄为 1,因为它们挺过了一次 Minor GC。此时,伊 #### 元空间 -Java 8 引入了元空间,并用它替换了永久代。这么做的好处是自动调整大小,避免了 内存不足OutOfMemory(OOM)错误。 +Java 8 引入了元空间Metaspace,并用它替换了永久代。这么做的好处是自动调整大小,避免了 内存不足OutOfMemory(OOM)错误。 ### 总结 本文讨论了各种不同的 JVM 内存“代”,以及它们是如何在分代垃圾回收算法中起作用的。对于程序员来说,掌握 Java 的内存管理机制并不是必须的,但它能够帮助你更好地理解 JVM 处理程序中的变量和类实例的方式。这种理解使你能够规划和排除代码故障,并理解特定平台固有的潜在限制。 -正文配图来自:Jayashree Huttanagoudar,CC BY-SA 4.0 +*正文配图来自:Jayashree Huttanagoudar,CC BY-SA 4.0* -------------------------------------------------------------------------------- @@ -138,7 +137,7 @@ via: https://opensource.com/article/22/6/garbage-collection-java-virtual-machine 作者:[Jayashree Huttanagoudar][a] 选题:[lkxed][b] 译者:[lkxed](https://github.com/lkxed) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出