写点什么

第 9 周作业

用户头像
Steven
关注
发布于: 2020 年 12 月 20 日

简述 JVM 垃圾回收原理



JVM 垃圾回收 就是将 JVM 堆中的已经不再被使用的对象清理掉,释放宝贵的内存资源。

垃圾判断

JVM 通过一种可达性分析算法进行垃圾对象的识别,具体过程是:从线程栈帧中的局部变量,或者是方法区的静态变量出发,将这些变量引用的对象进行标记,然后看这些被标记的对象是否引用了其他对象,继续进行标记,所有被标记的对象都是被使用的对象,而那些没有被标记的对象就是可回收的垃圾对象了。



Java 虚拟机规范不要求虚拟机在方法区实现 GC,这个区域 GC 的“性价比”比较低。

在堆中,尤其是在新生代,常规应用进行一次 GC 一般可以回收 70%-95% 的空间。

相关算法

标记-清除

将垃圾回收分为两个阶段:标记阶段和清除阶段。通过垃圾判断做标记。然后,在清除阶段,清除所有未被标记的对象。该算法最大的问题是存在大量的空间碎片,因为回收后的空间是不连续的。在对象的堆空间分配过程中,尤其是大对象的内存分配,不连续的内存空间的工作效率要低于连续的空间。

复制算法

将现有的内存空间分为两块,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。



如果系统中的垃圾对象很多,复制算法需要复制的存活对象数量并不会太大。因此在真正需要垃圾回收的时刻,复制算法的效率是很高的。又由于对象在垃圾回收过程中统一被复制到新的内存空间中,因此,可确保回收后的内存空间是没有碎片的。该算法的缺点是将系统内存折半。

标记-压缩算法

一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。

增量算法

在垃圾回收过程中,CPU 处于消耗很高的状态。应用程序所有的线程都会挂起,暂停一切正常的工作,等待垃圾回收的完成。



让垃圾收集线程和应用程序线程交替执行。每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。

分代

将内存区间根据对象的特点分成几块,根据每块内存区间的特点,使用不同的回收算法,以提高垃圾回收的效率。



在年轻代就选择效率较高的复制算法。当一个对象经过几次回收后依然存活,对象就会被放入称为老生代的内存空间。可以对老年代的回收使用与新生代不同的标记-压缩算法,以提高垃圾回收效率。

JVM 垃圾回收器分类

串行收集器

串行收集器主要有两个特点:第一,它仅仅使用单线程进行垃圾回收;第二,它独占式的垃圾回收。

新生代串行处理器使用复制算法,实现相对简单,逻辑处理特别高效,且没有线程切换的开销。



老年代串行收集器使用的是标记-压缩算法。和新生代串行收集器一样,它也是一个串行的、独占式的垃圾回收器。

并行收集器

并行收集器是工作在新生代的垃圾收集器,它只简单地将串行回收器多线程化。它的回收策略、算法以及参数和串行回收器一样。



并行回收器也是独占式的回收器,在收集过程中,应用程序会全部暂停。但由于并行回收器使用多线程进行垃圾回收,因此,在并发能力比较强的 CPU 上,它产生的停顿时间要短于串行回收器。

CMS 收集器

CMS 工作时,主要步骤有:初始标记、并发标记、重新标记、并发清除和并发重置。其中初始标记和重新标记是独占系统资源的,而并发标记、并发清除和并发重置是可以和用户线程一起执行的。因此,从整体上来说,CMS 收集不是独占式的,它可以在应用程序运行过程中进行垃圾回收。



根据标记-清除算法,初始标记、并发标记和重新标记都是为了标记出需要回收的对象。并发清理则是在标记完成后,正式回收垃圾对象;并发重置是指在垃圾回收完成后,重新初始化 CMS 数据结构和数据,为下一次垃圾回收做好准备。并发标记、并发清理和并发重置都是可以和应用程序线程一起执行的。

G1 收集器

G1 收集器是基于标记-压缩算法的。因此不会产生空间碎片,也没有必要在收集完成后,进行一次独占式的碎片整理工作。



G1 收集器还可以进行非常精确的停顿控制。可以更充分的利用 CPU ,多核环境下的硬件优势来缩短停顿时间。



筛选回收,对各个 Region 的回收价值和成本进行排序,每次根据允许的收集停顿时间,优先回收价值最大的 Region。



用户头像

Steven

关注

还未添加个人签名 2008.07.18 加入

还未添加个人简介

评论

发布
暂无评论
第 9 周作业