Java的JVM GC(Garbage Collection)垃圾回收原理机制及算法

简介: Java的JVM GC(Garbage Collection)垃圾回收原理机制及算法Java GC(Garbage Collection)垃圾回收机制,Java VM中,存在自动内存管理和垃圾清理机制。
Java的JVM GC(Garbage Collection)垃圾回收原理机制及算法


Java GC(Garbage Collection)垃圾回收机制,Java VM中,存在自动内存管理和垃圾清理机制。GC机制对JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,防止出现内存泄露和溢出问题。Java中不能显式分配和注销内存。有些开发者把对象设置为null或者调用System.gc()显式清理内存。设置为null至少没什么坏处,但是调用System.gc()会一定程度上影响系统性能。Java开发人员通常无须直接在程序代码中清理内存,而是由垃圾回收器自动寻找不必要的垃圾对象,并且清理掉它们。


Java GC主要做三件事:
(a)哪些内存需要GC?
(b)何时需要执行GC?
(c)以何策略执行GC?


Java中什么哪些内存需要GC回收?
JVM会分配一个运行时内存空间。包括5大部分:程序计数器(Program Counter Register)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。其中程序计数器、虚拟机栈、本地方法栈是每个线程私有内存空间,随线程而生,随线程而亡。这3个区域内存分配和回收都是确定的,无需考虑内存回收的问题。
但方法区和堆就不同了,一个接口的多个实现类需要的内存可能不一样,只有在程序运行期间才会知道会创建哪些对象,这部分内存的分配和回收都是动态的,GC主要关注的是这部分内存。GC主要进行回收的内存是JVM中的方法区和堆,涉及到多线程(指堆)、多个对该对象不同类型的引用(指方法区),才会涉及GC的回收。
小结:Java GC针对的是JVM中堆和方法区。


Java GC机制启动之前,需要确定堆内存中哪些对象是存活的,一般有两种方法:引用计数法和可达性分析法。
引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。引用计数法实现简单,判定高效,但不能解决对象之间相互引用的问题。
可达性分析(Reachability Analysis):从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。通过称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,搜索路径称为 “引用链(Reference Chain)”,以下对象可作为GC Roots:
(a)本地变量表中引用的对象
(b)方法区中静态变量引用的对象
(c)方法区中常量引用的对象
(d)Native方法引用的对象
当一个对象到 GC Roots 没有任何引用链时,意味着该对象可以被回收。
小结:Java GC垃圾回收机制,回收的是已死的Java对象(引用无法可达)。


Java GC垃圾回收算法


(一)标记 -清除算法
   “标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。之所以说它是最基础的内存回收算法,是因为后续的算法都是基于这种思路、并对其缺点进行改进而得到的。
主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存时候,不得不提前触发另一次垃圾收集动作。


(二)复制算法
“复制”(Copying)内存回收算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为原来的一半,持续复制长生存期的对象则导致效率降低。


(三)Java GC的分代垃圾回收机制
GC分代回收算法
GC分代的假设:绝大部分对象的生命周期都非常短暂,存活时间短。
“分代回收”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。


GC垃圾回收器会在下面两种情况下启动:
(a)大多数对象会很快变得不可达。
(b)只有很少的由老对象(创建时间较长的对象)指向新生对象的引用。
为强化这一假设,Java虚拟机在物理上划分为两个逻辑内存代——新生代(Young Generation)和老年代(Old Generation)。新生代(Young Generation): 新生代空间用来保存那些第一次被创建的Java对象,分为三个空间:
(a)一个伊甸园空间(Eden )
(b)两个幸存者空间(Survivor )
一共有三个空间,其中包含两个幸存者空间。每个空间的执行顺序如下:
(a)绝大多数刚刚被创建的对象会存放在伊甸园空间。
(b)在伊甸园空间执行了第一次GC之后,存活的对象被移动到其中一个幸存者空间。
(c)此后,在伊甸园空间执行GC之后,存活的对象会被堆积在同一个幸存者空间。
(d)当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。之后会清空已经饱和的那个幸存者空间。
(e)在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。
在新生代中,使用“停止-复制”算法进行内存清理。绝大多数最新被创建的对象会被分配到这里,由于大部分对象在创建后会很快变得不可到达,所以很多对象被创建在新生代,然后消失。对象从这个区域消失的过程称为“Minor GC” 。
老年代(Old Generation): 对象没有变得不可达,并且从新生代中存活下来,会被拷贝到这里。其所占用的空间要比新生代多。也正由于其相对较大的空间,发生在老年代上的GC要比新生代少得多。对象如果在年轻代存活了足够长的时间而没有被清理掉(即在几次Young GC后存活了下来),则会被复制到年老代,年老代的空间一般比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。当年老代内存不足时,将执行Major GC,也叫 Full GC。老年代存储的对象比年轻代多得多,而且不乏大对象,对老年代进行内存清理时,如果使用停止-复制算法,则相当低效。一般,老年代用的算法是标记-整理算法,即:标记出仍然存活的对象(存在引用的),将所有存活的对象向一端移动,以保证内存的连续。
小结:Java内存分配和回收机制是:分代分配,分代回收。新生代中,每次垃圾收集时都有大批对象死去,只有少量存活,就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。老年代中,其存活率较高、没有额外空间对它进行分配担保,就应该使用“标记-整理”或“标记-清理”算法进行回收。


Java GC优化永远是最后一项任务。因为Java GC将“Stop the World”(串行GC暂时中断程序执行)。Stop-the-world会在任何一种GC算法中发生。Stop-the-world意味着 JVM 因为要执行GC而停止了应用程序的执行。当Stop-the-world发生时,除了GC所需的线程以外,所有线程都处于等待状态,直到GC任务完成。GC优化很多时候就是指减少Stop-the-world发生的时间。GC优化的根本原因,垃圾收集器清除Java创建的对象,GC执行的次数,即需要被垃圾收集器清理的对象个数,与创建对象的数量成正比,因此,应该减少创建对象的数量。
GC优化两个目的:
(a)将转移到老年代的对象数量降到最少。对象被创建在伊甸园空间,而后转化到幸存者空间,最终剩余的对象被送到老年代。某些比较大的对象会在被创建在伊甸园空间后,直接转移到老年代空间。老年代空间上的GC处理会比新生代花费更多时间。因此,减少被移到老年代对象的数据可以显著地减少Full GC的频率。减少被移到老年代空间的对象数量,可能被误解为将对象留在新生代。但是,这是不可能的。取而代之,你可以调整新生代空间的大小。
(b)减少Full GC的执行时间。Full GC执行时间比Minor GC要长很多。

相关文章
|
27天前
|
监控 算法 Java
Java虚拟机(JVM)的垃圾回收机制深度解析####
本文深入探讨了Java虚拟机(JVM)的垃圾回收机制,旨在揭示其背后的工作原理与优化策略。我们将从垃圾回收的基本概念入手,逐步剖析标记-清除、复制算法、标记-整理等主流垃圾回收算法的原理与实现细节。通过对比不同算法的优缺点及适用场景,为开发者提供优化Java应用性能与内存管理的实践指南。 ####
|
19天前
|
监控 算法 Java
Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
25 0
|
18天前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
22天前
|
机器学习/深度学习 监控 算法
Java虚拟机(JVM)的垃圾回收机制深度剖析####
本文深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法、性能调优策略及未来趋势。通过实例解析,为开发者提供优化Java应用性能的思路与方法。 ####
31 1
|
25天前
|
监控 算法 Java
Java虚拟机垃圾回收机制深度剖析与优化策略####
【10月更文挑战第21天】 本文旨在深入探讨Java虚拟机(JVM)中的垃圾回收机制,揭示其工作原理、常见算法及参数调优技巧。通过案例分析,展示如何根据应用特性调整GC策略,以提升Java应用的性能和稳定性,为开发者提供实战中的优化指南。 ####
40 5
|
27天前
|
存储 算法 安全
JVM常见面试题(四):垃圾回收
堆区域划分,对象什么时候可以被垃圾器回收,如何定位垃圾——引用计数法、可达性分析算法,JVM垃圾回收算法——标记清除算法、标记整理算法、复制算法、分代回收算法;JVM垃圾回收器——串行、并行、CMS垃圾回收器、G1垃圾回收器;强引用、软引用、弱引用、虚引用
|
25天前
|
存储 算法 Java
JVM进阶调优系列(10)敢向stop the world喊卡的G1垃圾回收器 | 有必要讲透
本文详细介绍了G1垃圾回收器的背景、核心原理及其回收过程。G1,即Garbage First,旨在通过将堆内存划分为多个Region来实现低延时的垃圾回收,每个Region可以根据其垃圾回收的价值被优先回收。文章还探讨了G1的Young GC、Mixed GC以及Full GC的具体流程,并列出了G1回收器的核心参数配置,帮助读者更好地理解和优化G1的使用。
|
26天前
|
监控 Java 测试技术
Elasticsearch集群JVM调优垃圾回收器的选择
Elasticsearch集群JVM调优垃圾回收器的选择
46 1
|
25天前
|
算法 Java
JVM有哪些垃圾回收算法?
(1)标记清除算法: 标记不需要回收的对象,然后清除没有标记的对象,会造成许多内存碎片。 (2)复制算法: 将内存分为两块,只使用一块,进行垃圾回收时,先将存活的对象复制到另一块区域,然后清空之前的区域。用在新生代 (3)标记整理算法: 与标记清除算法类似,但是在标记之后,将存活对象向一端移动,然后清除边界外的垃圾对象。用在老年代
22 0
|
28天前
|
监控 算法 Java
深入理解Java虚拟机(JVM)的垃圾回收机制
【10月更文挑战第21天】 本文将带你深入了解Java虚拟机(JVM)的垃圾回收机制,包括它的工作原理、常见的垃圾收集算法以及如何优化JVM垃圾回收性能。通过本文,你将对JVM垃圾回收有一个全新的认识,并学会如何在实际开发中进行有效的调优。
41 0
下一篇
DataWorks