浅谈 GC
GC 即垃圾回收机制,回收的是 new 出来的对象,所以在聊 GC 前先看看对象的组成。
对象的组成部分
对象在内存中存储可以分为 3 个区域:对象头、实例数据、对齐填充。下面图中就是一个普通对象实例的数据结构
对象头
HotSpot 虚拟机的对象头包括两部分信息:
- Mark Word
第一部分 mark word 用于存储对象自身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有锁、偏向线程ID、偏向时间戳等,长度为 32bit 或 64bit。 - Klass Pointer
另一部分是 klass 类型指针,即对象指向它的类元数据(在方法区中)的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
实例数据
实例数据部分是对象真正存储的有效信息,也是在代码中所定义的各种类型的字段内容
对齐填充
占位符作用,由于 HotSpot VM 的自动内存管理系统要求对象起始位置必须是 8 字节的整数倍,即对象的大小必须是 8 字节的整数倍。而对象头正好是 8 字节的倍数,因此,当实例数据部分不是 8 字节的整数倍时,就需要通过对齐填充来补全
GC(垃圾回收)
一个程序只要在运行中,那么就会不停的 new 对象,总有一个时间点 Eden 区域会放满,一旦 Eden 区满了之后,虚拟机就会执行 GC,此时的 GC 为 minor GC。
那么哪些对象是会被回收的垃圾对象呢?那就涉及到可达性分析和 GC Roots 根对象了,这里不详细展开,简单说一下哪些对象属于** GC Roots** 根对象:
- 虚拟机栈(栈帧中的局部变量表)中引用的对象
- 本地方法栈中JNI(Native 方法)引用的对象
- 方法区中静态属性引用的对象
- 方法区中常量引用的对象
下面简单说说回收的过程
新对象分配在 Eden 区
Eden 区放满后,执行 minor GC,存活的对象会被移到 from 区。上图中对象存活下来,对象2被回收了
在对象头的组成部分 Mark Word 里存储 GC 分代年龄,一个对象每经历一次 GC,那么它的年龄就 +1,如上图所示
当又有新对象放满 Eden 区时,就会再次执行 minor GC,但是这一次会带着 from/to(只有一块区域存放对象,参考复制-回收算法)区一起 GC,然后将 Eden 区和 from/to 区存活的对象都移到 to/from 区,并且对象头中的分代年龄都 +1
当 Eden 区又又一次被放满后,继续执行上述 GC 过程。
如果一个对象的分代年龄达到 15(默认),就会被移到老年代,那会不会没达到限定年龄就直接进入老年代呢?当然会了,当 from/to 区的空间不够时,就直接存放到老年代,这里简单举例了两种情况,还有其它将对象存入老年代的规则。
最后,随着程序的不断运行,老年代也会被对象占满,这时候发生的 GC 就是 Full GC 了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)