JVM虚拟机三之GC垃圾回收
JVM虚拟机 GC垃圾回收
垃圾回收主要做三件事:哪些内存需要回收,什么时候回收,怎么回收。
垃圾回收主要的知识点:判断对象是否存活,垃圾收集算法,各类垃圾收集器以及垃圾回收过程。
Java对象之死
1.引用计数法,JVM没有用。但是每个教程都会告诉你。是不是因为《深入理解Java虚拟机》太过经典,里边介绍了这用引用计数法,所以往后的教程都需要这个啊。
我就记一句话:不能解决互相引用,循环引用。
2.可达性分析
通过一些GC Roots对象作为起点,然后一路标记引用对象,存放到存活引用集合中。没有被标记的对象就作为被回收的对象了。
GC Roots对象的分类:
- 全局性引用,方法区的静态对象,常量对象的引用
- 执行上下文,对Java方法栈帧中的局部变量的对象引用,对JNI handles对象引用
- 已启动且未停止的Java线程
存在的问题:
- 误报:已经可以回收的对象,被标记为存活,垃圾回收不到,可能性较小,占用一会内存,影响不大。
- 楼板:正在引用的对象没有被标记存活,被垃圾回收,直接导致JVM崩溃。 - 通过垃圾回收时,STW确保可达性分析的准确性,避免漏报。
垃圾回收算法
- 标记-清除算法
- 标记无引用的死亡对象所占据的空闲内存,记录到空闲列表(free list)。
- 创建对象的时候,从free list表中找到空闲内存,分配给新的对象。
- 这个算法简单高效,但是会产生很对的内存碎片。
- JVM堆中的对象,必须是连续分布的,所以极端的情况下可能会剩余内存足,但是找不到符合要求大小的连续的内存,导致无法分配对象。
- 在CMS垃圾回收器,使用了这种算法,GC暂停时间短,但存在算法缺陷。
- 标记-复制算法
- 将内存空间分为两份,通过from和to两个指针维护,from指针指向的内存区域分配分配内存
- 垃圾回收时,将存活对象复制到to指针指向的内存区域,并交换from指针和to指针。
- 解决内存碎片的问题,但是造成内存空间的浪费,只有一半用来存储对象。
- 标记 - 压缩算法
- 标记阶段与标记-清除算法一样,在清理的过程中,先将存活的对象向内存一边移动整理,然后再清理其他的空间。
- 这种算法解决了标记-清除算法中产生的内存碎片问题,但是压缩算法增加了开销。
垃圾收集器
- 新生代
- Serial(连续的)
采用标记-清除算法,简单高效的单核机器,Clinet模式下默认新生代收集器。
- Parallel ParNew
采用标记-复制算法,GC线程并行版本,在单CPU下效果不明显,常用于Client模式下的JVM。
- Parallel Scavenge
标记-复制算法,目标是达到可控制吞吐量(吞吐量 = 用户代码运行时间/(用户代码运行时间+垃圾回收时间))
- 老年代
- Serial Old
标记-压缩算方法;性能一般,单线程版本。1.5版本之前,与Parallel Scavenge配合使用;作为CMS的后备预案。
- Parallel Old
采用标记压缩算法;GC多线程并行,替代了Serial Old与Parallel Scavenge配合使用。
- CMS
标记-清除算法;对CPU资源敏感,停顿时间长;会产生碎片,通过参数开启碎片的合并整理。
- g1
采用标记-压缩算法;适用于大内存机器,GC多线程并行执行,低停顿,高回收效率。
总结
大体的记录了JVM垃圾回收的内容,垃圾对象的判断,垃圾回收算法,垃圾收集器。
分类:
Java之JVM虚拟机
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性