JVM垃圾回收

发布于:2025-03-26 ⋅ 阅读:(24) ⋅ 点赞:(0)

JVM垃圾回收深度解析

我们的程序从主方法开始,所有申请的对象都是一层层的方法往下创建的。

如果一个方法中创建的内存对象,在方法执行完之后还需使用,程序必然需要在其上一层方法中,通过一个引用地址指向这个内存对象,这样一层层的引用就会形成一个引用链

 

对于那些在方法中创建,但在外部方法中,不需要使用的内存对象,我们也不会刻意在外层使用一个引用地址指向它,等方法执行完之后,这种对象就会变成游离状态

也就是我们可以回收的内存对象。 

 

这种通过判断一个对象是否可以基于引用链溯源到主方法中某个引用的算法,就是可达性分析算法

java虚拟机就是通过这种算法标记出所有不可回收的内存对象,然后就可以回收剩下没有别标记的垃圾内存。

一般有三种回收算法

1、标记清理法:就是清理那些可以回收的内存区域。

优缺点:标记清理算法虽然快,但是会产生碎片空间

2、复制法:把一整块内存分为两部分,每次只使用一半,垃圾回收时,把不需要回收的拷贝到另一半上,然后把当前一半全部清理掉。

优缺点:复制算法虽然没有碎片空间,但是只有一半内存可用。

 

3、标记整理法:就是把可回收的内存对象清理掉后,将剩余的对象整理到整块内存的头部。

优缺点:标记整理算法虽然既不浪费内存,也没有碎片空间但耗时长

 

在实际情况下,会将他们组合起来使用,一般情况下,Java虚拟机会把申请的内存区域划分为较小的新生代和较大的老年代两个区域

程序运行过程中,创建的对象会优先放置到新生代中,

对于那些经过多次垃圾回收,依然存活的对象则会迁移到老年代。

新生代中使用的回收算法,就是复制法

因为大部分的内存对象,就是在那种子方法中创建,使用后就没有用了的对象,所以垃圾回收时,需要进行复制的对象很少,这样就能实现高效回收的同时,不产生碎片空间。

另外为了进一步提高内存的利用率,新生代又被分成了两个S区和一个E区一个S区仅占新生代总大小的1/10

每次使用时,都是使用一个S区和E区,当执行垃圾回收时,将S区和E区中不用回收的少量对象复制到另一个S区中,然后清空当前的S区和E区,如此一来便可以把内存的使用率从50%提高到90%

注:黄色为不可回收对象

 

问:如果复制的对象多S区放不下呢?

答:放不下的对象则会直接放到老年代,放心经过多年的实践证明,这种情况并不多。

老年代则大部分使用标记整理算法

问:那标记整理算法不是很慢吗?并且在整理过程中为了防止程序随意操作内存,程序会被短暂的停顿。

答:早期的垃圾回收器基于单线程实现确实比较慢,一次垃圾回收可能让系统停顿数秒,但经过不断的发展,随着多线程增量回收,多区域划分等技术的引入如今的G1垃圾收集器已经可以将停顿时间稳定在100毫秒左右这在用户层面已经几乎没有感知了

学习笔记来源: https://v.douyin.com/i5T93R2M/


网站公告

今日签到

点亮在社区的每一天
去签到