JVM的垃圾回收机制(GC机制)

在Java代码运行的过程中,JVM发现 某些资源不需要再使用的时候,就会自动把资源所占的内存给回收掉,就不需要程序员自行操作了。"自动回收资源" 就是JVM的**"垃圾回收机制","** 垃圾回收机制"也称**"GC机制"**。

对于Java代码来说,"垃圾回收机制"的回收对象 就是**"堆"上的对象**。因为"栈"上的局部变量,跟随栈帧的生命周期,一个方法执行结束,栈帧销毁,内存也就释放了;"方法区"中的静态变量,跟随着"类"的生命周期,因此静态变量是在程序运行期间始终存在的,无需释放。那么"垃圾"就是 "堆"中的对象。

垃圾回收机制可以分为两大步骤:"找垃圾""回收垃圾"

1. 找垃圾

"找垃圾"有两种方式,分别是引用计数 (python的方式) 和 可达性分析(Java的方式)。

1.1 引用计数

对于一个new出来的对象,会单独安排一块内存空间 来保存一个计数器。这个计数器 就用来描述当前这个对象 有几个引用指向它。当计数器为0时,也就意味着没有引用指向这个对象了,那么这个对象就是"垃圾"了。

1.2 可达性分析

在Java代码运行的过程中,会有一个或一组扫描线程周期性地扫描代码中的所有对象 。这个扫描线程,会从一些特定的对象出发,尽可能地进行遍历访问,把所有能够访问到的对象 标记为 可达。反之,经过扫描之后,没有被标记的对象,就是"垃圾"了。可达性分析 是周期性地进行,会消耗一定地系统资源。

2. 回收垃圾

2.1 标记清除

把找到的**"垃圾"对象直接释放掉** ,这就是标记清除的回收方式。这种方式并不好,因为这样的回收垃圾的方法会导致内存中有很多的内存碎片。随着程序的运行,内存碎片会越来越多,这就会导致后续申请内存空间时非常困难。回收垃圾的目的本就是为了释放内存空间,从而让其它进程申请到内存空间,但这种释放内存的方式并没有达到想要的效果。

如下图,虽然此时内存中共有3MB的空闲内存,但都不是连续的,因此其它进程只能申请到小于等于1MB的内存。

2.2 复制算法

复制算法是对"标记清除"方式的优化,申请到内存之后,只使用内存的一半存储有效对象。出现有内存碎片时,就将有效对象归类到一起,也就是把有效对象拷贝到 存储有效对象的一半内存中,然后再将另一半内存进行释放。

复制算法能够防止出现内存碎片,但这个方式的内存利用率不高,且如果有效对象很多,拷贝的成本就很大了,效率太低。

2.3 标记整理

标记整理 则是对 标记清除 和 复制算法 的优化,当内存中出现内存碎片时,则会将有效对象拷贝到空闲的内存中,将其覆盖,类似于顺序表删除元素的操作,这样就可以避免内存碎片了。但也涉及到了同样的问题,当需要拷贝的对象太多时 ,也会有很大的内存开销

2.4 分代回收

JVM在回收垃圾时,采用的方式一般就是**"分代回收"** 。此方法则是将堆区 划分为 两个区域,分别是**"新生代"** 和 "老年代"。"新生代"区域又划分为两个区域,分别是"伊甸区" 和 "幸存区",幸存区被划分为两块大小相同的区域。

刚创建出来的对象 都会出现在**"新生代"** 区域,"GC扫描线程" 会对 新生代区域的对象进行扫描。虽然从 对象的诞生 到 第一轮可达性分析扫描的过程 不会间隔较长时间,但在这段时间里,大部分对象都会成为"垃圾"。因为,这段时间对于程序而言,已经是挺长的时间了,在这个时间段中,对象的引用很快就会随着方法的执行完毕就销毁了,那么这些对象就会成为"垃圾"了。

经过一轮扫描之后,幸存下来的对象 就会被拷贝到"幸存区"的一半区域中 ,"伊甸区"的内存就可以整体释放了。虽然这个过程涉及到了拷贝对象的操作,但一般拷贝的对象并不多,因此内存开销是可承受的。GC扫描线程会在后续的扫描过程中,去扫描"幸存区"中的对象。如果幸存区中的对象经过一轮扫描后仍在存在 ,则会把这个对象拷贝到幸存区的另一半中 。在幸存区中,每经过一轮扫描,幸存下来的对象都会被拷贝到幸存区的另一半。幸存的对象在幸存区来回拷贝的过程中,会有许多对象被回收掉。如果经过多次扫描幸存区中的某些对象一直存在JVM则会把这些对象放在"老年代"中。相比于"新生代","老年代"区域的扫描频率要低,因为JVM认为"老年代"中的对象存活的时间较长。

将整个堆区划分为"新生代"和"老年代",也是为了降低GC扫描的开销。

分代回收则是通过上述的方式来进行垃圾回收,也是综合了 标记清除,复制算法,标记整理的优点,降低内存开销的同时,也避免了内存碎片。

相关推荐
吴冰_hogan3 小时前
JVM(Java虚拟机)的组成部分详解
java·开发语言·jvm
东阳马生架构10 小时前
JVM实战—1.Java代码的运行原理
jvm
ThisIsClark13 小时前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
王佑辉13 小时前
【jvm】内存泄漏与内存溢出的区别
jvm
大G哥15 小时前
深入理解.NET内存回收机制
jvm·.net
泰勒今天不想展开15 小时前
jvm接入prometheus监控
jvm·windows·prometheus
东阳马生架构1 天前
JVM简介—3.JVM的执行子系统
jvm
程序员志哥2 天前
JVM系列(十三) -常用调优工具介绍
jvm
后台技术汇2 天前
JavaAgent技术应用和原理:JVM持久化监控
jvm