【JVM】——GC垃圾回收机制(图解通俗易懂)

简介: GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)

  image.gif 编辑

阿华代码,不是逆风,就是我疯

你们的点赞收藏是我前进最大的动力!!

希望本文内容能够帮助到你!!

目录

一:引入

二:垃圾回收

1:识别出垃圾

编辑(1)引用计数机制

问题一:计数器占用内存空间

问题二:循环引用的问题

(2)可达性分析

2:内存释放机制

(1)标记——清除

(2)复制算法

优点

缺点

(3)标记—整理

优点

缺点

(4)分代回收


本文GC的垃圾回收机制是重点

一:引入

在C语言中。malloc可以申请内存,free释放内存,申请到的内存的生命周期,会跟随整个进程。这一点对服务器程序非常的不好,如果服务器对每个请求都要去申请一块内存,申请的越来越多,最后导致没有空闲内存了。就会发生内存泄露问题。

像之前我们写的TCP回显服务器中,就存在accept接受一个请求后,就一定要在finally中去.close关闭文件。

那么我们能否实现让程序自动释放内存,而不是让程序员来手动释放呢?JVM就做到了这一点。

二:垃圾回收

GC垃圾回收中有一个很重要的问题:“STW”(stop the world)问题,触发垃圾回收的时候,很有可能造成当前程序的其它业务逻辑被暂停,Java发展到现在,已经可以把“STW”控制在1ms以内了

通过上一篇文章的学习,我们知道JVM中的内存有好几块——程序计数器,栈,堆,元数据区,这里面“堆”就是GC垃圾回收的主要战场

垃圾回收,准确的说可以是“回收对象”,而非回收内存

image.gif 编辑

1:识别出垃圾

image.gif 编辑(1)引用计数机制

试想如果有多个引用指向同一个对象,那么这个对象什么时候被判定为垃圾就是一件麻烦的事情了,所以我们引入计数机制,这种思想方法并没有在JVM中进行使用,但是广泛应用于其它主流语言的垃圾回收机制中——给对象安排一个额外的空间,空间里保存当前这个对象有几个引用

image.gif 编辑

专门有一个扫描线程,去获取到当前有多少个引用指向这个对象,如果计数为0,这个对象就会被当成垃圾,被回收掉。但是这种机制也是有一些问题的

image.gif 编辑

问题一:计数器占用内存空间

试想每一个对象都要有一个计数器进行计数,如果对象非常多的话,计数器占用的内存空间就非常大了

问题二:循环引用的问题

image.gif 编辑

image.gif 编辑

此时要使用第一个对象,那就需要获得第一个对象的引用,第一个对象的引用又在第二个对象中;那么就需要获得第二个对象的引用,第二个对象的引用又在第一个对象中,那么就需要获取第一个对象的引用。闭环了(裂开!!有点像死锁

(2)可达性分析

JVM中使用的就是可达性分析

在代码中,会定义许多变量,JVM中存在扫描线程,会对已有的这些变量进行遍历,尽可能的去访问到更多的对象——  能被访问到的对象,就不会被当做垃圾,访问不到的对象,自然就是垃圾。

注:不可达是有传递性这种效果的

image.gif 编辑

2:内存释放机制

把标记为垃圾的对象所占的内存空间进行回收,这里我们介绍4种释放方式

(1)标记——清除

image.gif 编辑

这种标记——清除的策略,也会带来一些问题:内存碎片

在回收完黑色方块所处的内存空间后(假设为4M),剩余的白色方块空闲内存空间为6M,但是这6M的内存空间并不是连续的一段空间,而是一段离散的、小的空间

这就造成了一个问题——剩下的实际能使用的内存空间是小于6M的

再通俗一点的举例:此时有一个6M大小的对象需要存进内存空间,肯定不能放进去嘛,因为这不是连续的一段内存空间

(2)复制算法

image.gif 编辑

优点

①规避了内存碎片的问题

缺点

①申请的内存空间只有利用率太低,只有一半左右

②如果需要复制的对象太多,那么成本就太高

(3)标记—整理

image.gif 编辑

优点

①有效解决内存碎片的问题

②不像复制算法那样浪费太多空间

缺点

①搬运的成本较高

(4)分代回收

分代回收机制:依据不同种类的对象,采取不同的方式

JVM中有专门的扫描线程,来扫描标记对象,根据对象的年龄差异把整个内存分为新生代老年代两个区域部分

其中新生代区域又分为两个部分——伊甸区,生存区

对象年龄:如果一个对象被扫描一次后,判定不是垃圾,就年龄+1(初始年龄=0)

image.gif 编辑

①代码中new出来的对象都放到伊甸区,当扫描线程第一遍扫描时,标记为垃圾的对象就进行回收,剩余的对象通过复制算法复制到生存区1中

注:绝大多数对象都活不过伊甸区,只有少数能够撑住第一轮,被复制到生存区1中,此时这些对象年龄+1

②扫描线程第二遍扫描新生代,重复①,而生存区1中的对象大部分又被标记为垃圾进行GC回收了,只有一丢丢存活下来的对象继续被复制到生存区2中,此时这些对象年龄再+1,变为2

注:第二遍扫描包含伊甸区和生存区,老年代区被扫描的频率很低<后面会解释>

③经过若干轮,发现有年龄非常大的对象,那么就会认为这个对象的生命周期很长,就会把这个对象从生存区拷贝到老年代区中

④扫描线程继续工作,只不过老年代区扫描的频率非常低,大大节省了开销

⑤老年代区的对象挂了的话,就会按照“标记—整理”的方式进行回收,释放内存

上述JVM分代回收是GC中的核心思想,实际还有很多细节,感兴趣的铁铁可以深入研究一下~~

相关文章
|
1月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
220 55
|
3月前
|
存储 监控 Java
JVM实战—8.如何分析jstat统计来定位GC
本文详细介绍了使用jstat、jmap和jhat等工具分析JVM运行状况的方法,以及如何合理优化JVM性能。内容涵盖新生代与老年代对象增长速率、Young GC和Full GC的触发频率及耗时等关键指标的分析。通过模拟BI系统和计算系统的案例,展示了如何根据实际场景调整JVM参数以减少FGC频率,提升系统性能。最后汇总了常见问题及其解决方案,帮助开发者更好地理解和优化JVM运行状态。
JVM实战—8.如何分析jstat统计来定位GC
|
1月前
|
缓存 算法 Java
JVM深入原理(八)(一):垃圾回收
弱引用-作用:JVM中使用WeakReference对象来实现软引用,一般在ThreadLocal中,当进行垃圾回收时,被弱引用对象引用的对象就直接被回收.软引用-作用:JVM中使用SoftReference对象来实现软引用,一般在缓存中使用,当程序内存不足时,被引用的对象就会被回收.强引用-作用:可达性算法描述的根对象引用普通对象的引用,指的就是强引用,只要有这层关系存在,被引用的对象就会不被垃圾回收。引用计数法-缺点:如果两个对象循环引用,而又没有其他的对象来引用它们,这样就造成垃圾堆积。
51 0
|
1月前
|
算法 Java 对象存储
JVM深入原理(八)(二):垃圾回收
Java垃圾回收过程会通过单独的GC线程来完成,但是不管使用哪一种GC算法,都会有部分阶段需要停止所有的用户线程。这个过程被称之为StopTheWorld简称STW,如果STW时间过长则会影响用户的使用。一般来说,堆内存越大,最大STW就越长,想减少最大STW,就会减少吞吐量,不同的GC算法适用于不同的场景。分代回收算法将整个堆中的区域划分为新生代和老年代。--超过新生代大小的大对象会直接晋升到老年代。
47 0
|
3月前
|
存储 监控 Java
JVM实战—7.如何模拟GC场景并阅读GC日志
本文主要介绍了:如何动手模拟出频繁Young GC的场景、JVM的Young GC日志应该怎么看、编写代码模拟动态年龄判定规则进入老年代、编写代码模拟S区放不下部分进入老年代、JVM的Full GC日志应该怎么看。
133 16
JVM实战—7.如何模拟GC场景并阅读GC日志
|
3月前
|
存储 算法 Java
G1原理—5.G1垃圾回收过程之Mixed GC
本文介绍了G1的Mixed GC垃圾回收过程,包括并发标记算法详解、三色标记法如何解决错标漏标问题、SATB如何解决错标漏标问题、Mixed GC的过程、选择CollectSet的算法
G1原理—5.G1垃圾回收过程之Mixed GC
|
3月前
|
缓存 算法 Java
JVM实战—4.JVM垃圾回收器的原理和调优
本文详细探讨了JVM垃圾回收机制,包括新生代ParNew和老年代CMS垃圾回收器的工作原理与优化方法。内容涵盖ParNew的多线程特性、默认线程数设置及适用场景,CMS的四个阶段(初始标记、并发标记、重新标记、并发清理)及其性能分析,以及如何通过合理分配内存区域、调整参数(如-XX:SurvivorRatio、-XX:MaxTenuringThreshold等)来优化垃圾回收。此外,还结合电商大促案例,分析了系统高峰期的内存使用模型,并总结了YGC和FGC的触发条件与优化策略。最后,针对常见问题进行了汇总解答,强调了基于系统运行模型进行JVM参数调优的重要性。
165 10
JVM实战—4.JVM垃圾回收器的原理和调优
|
3月前
|
缓存 监控 算法
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略
|
3月前
|
消息中间件 存储 算法
JVM实战—3.JVM垃圾回收的算法和全流程
本文详细介绍了JVM内存管理与垃圾回收机制,涵盖以下内容:对象何时被垃圾回收、垃圾回收算法及其优劣、新生代和老年代的垃圾回收算法、Stop the World问题分析、核心流程梳理。
JVM实战—3.JVM垃圾回收的算法和全流程
|
3月前
|
存储 算法 Java
G1原理—6.G1垃圾回收过程之Full GC
本文详细探讨了G1垃圾回收器对Full GC(FGC)的优化处理,涵盖FGC的前置处理、整体流程及并行化改进。重点分析了传统FGC串行化的局限性以及G1通过Region分区和RSet机制实现并行标记的优势,包括任务窃取提升效率、跨分区压缩以生成空闲Region等技术细节。此外,文章还介绍了G1的新特性——字符串去重优化,通过判断char数组一致性减少重复字符串占用内存,从而提升内存使用效率。总结部分全面回顾了G1在FGC中的各项优化措施及其带来的性能改善。
G1原理—6.G1垃圾回收过程之Full GC
OSZAR »