3.0、JVM 学习——垃圾回收器

本文深入解析HotSpot虚拟机JVM的堆内存模型,包括新生代、老年代及其垃圾回收机制,如MinorGC、MajorGC/FullGC,以及永久代的垃圾回收。探讨了HotSpot中字符串常量池的存储变化,对象存活性判断方法,和各种垃圾回收器的特点与配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

体能状态先于精神状态,习惯先于决心,聚焦先于喜好。

本文基于 HotSpot 虚拟机

本文基于 HotSpot 虚拟机

JVM 内存模型中的堆(Heap)

JVM 内存模型中的堆是整个JVM中占用内存最大的一块。

堆分为新生代和老年代

堆的内存空间可以被细分为新生代和老年代,新生代中的对象有着“朝生夕死”的特征,老年代中的对象则大概率的会"持久"的被应用调用。
新生代对象达到某些条件(比如新生代垃圾回收次数超过默认的15次,或同年龄对象超过Survivor一半)可以进入老年代。
超过阀值大小的大对象直接进入老年代。

新生代 和 Minor GC

在HotSpot 中,新生代又被细分为一个 Eden 和 两个Survivor,一个 Eden :一个 Survivor=8:1,即新生代的内存空间会被分为10份,Eden占8份, 两个Survivor各占一份。两个Survivor又被细分为 Survivor From 和 Survivor To
新生代空间有限,当条件满足时会触发新生代的垃圾回收——Minor GC,存活下来的对象放入 Survivor To,连同之前 Survivor From 依旧存活且没有进入老年代的对象一起存到 Survivor To,接着, Eden和Survivor From 会被置空, Survivor From和 Survivor To 互换角色,等待下一次垃圾回收。

老年代和 Major GC/Full GC

老年代空间也是有限的,老年代的垃圾回收叫做 Major GC/FullGC。
Major GC 和 FullGC 一个意思。

Minor GC 和 Full GC(Major GC) 的关系

新生带的 Minor GC 非常频繁,并且一般回收速度也很快。
老年代的 Full GC 一般会比新生代的 Minor GC 慢10倍以上。
Full GC 一般至少伴随一次 Minor GC ,但不是绝对的,比如 Paralle Scavenge 收集器的收集策略就有直接进行 Major GC(Full GC)的策略。

永久代和Major GC/Full GC

永久带是 HotSpot 虚拟机对JVM 规范中方法区的实现,
HotSpot JDK 对方法区的实现在JDK1.7以及之前被叫做永久代,其内存的物理位置和Java Heap(Java 堆)在一起,从JDK1.8开始,永久代被取消,取而代之的被称为元数据,其位置为操作系统的物理内存,比如你的计算机是4G内存,则方法区的实现大小理论上就是4G,而不是之前JVM的永久代的大小了.
在永久代和Java 堆在一起的时候,Full GC也会连带负责 永久代的垃圾回收。

HotSpot JVM 中字符串常量池 是 运行时常量池中特殊的存在

每一个类都有一个运行时常量池,而字符串类型为了实现存储效率最大化,字符串常量池是全局通用的

HotSpot JVM 常量池存储位置的变化
Jdk版本类常量运行时常量池字符串常量池垃圾回收
1.6及之前非堆(No-heap)-永久代非堆(No-heap)-永久代非堆(No-heap)-永久代Full Gc 回收永久代
1.7非堆(No-heap)-永久代heap(堆)heap(堆)Full Gc 回收永久代
1.8元数据(宿主机物理内存)heap(堆)heap(堆)

对象已死吗?

计数器法

为每一个对象的应用次数进行统计,当引用次数为0时,表示对象已死,在垃圾回收时可以回收该对象占用的空间——无法解决循环引用问题。

可达性分析法:HotSpot虚拟机使用该方法判断对象存活性

GC Roots 对象引用的表示存活,GC Roots 对象都不引用的表示对象已死,而已进行回收。

GC Roots 对象包含:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。

垃圾回收器

垃圾回收器也分为新生代的垃圾回收器和老年代的垃圾回收器搭配使用,直到 G1出现——G1是不区分新生代和永久代的。
G1 在 JDK 6u14 出现实验版本。

并行(Parallel)和并发(Concurrent)

垃圾回收器分为单线程和多线程。
其中,多线程垃圾回收器又可以分为并发和并行,并行的时候,用户的任务线程依旧是等待的,并发的则是用户线程和垃圾回收线程交替进行或在不同CPU进行。
stop the world 的意思是用户任务完全暂停等待垃圾回收。
单线程-stop the world
并行-stop the world
并发-不用stop the wolrd,CMS 的并发标记和并发清除不会 stop the world
没有任何一个垃圾回收器可以完全避免 stop the world ,包括G1,G1支持并发和并行和 CMS 很像。

新生代和垃圾回收器

新生代垃圾回收算法

新生代的对象有着“朝生夕逝”的特点,所以每次垃圾回收后“存活”下来的对象不多,因此使用的是复制算法,即将Eden区和from区的对象复制到to区。

新生代垃圾回收器种类

新生代的垃圾回收器有 Serial、ParNew、Parallel Scavenge
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

名称出现版本多线程回收算法搭配老年代回收器stop the world其他
Serial自JDK诞生复制算法CMS、Serial Old
ParNew1.3.1复制算法CMS、Serial Old
Parallel Scavenge1.4.0并行复制算法Parallel Old吞吐量
老年代和垃圾回收器
JDK 11 出现新的垃圾回收器 ZGC

https://developer.aliyun.com/article/726110

老年代垃圾回收器算法

老年代的对象大概率会继续存活下去,所以复制算法就不使用了,但是总是会有对象被清除的,虽然每次清楚的不如新生代多。
老年代存在两种垃圾回收算法,第一种是标记-整理算法(Serial Old),即老年代清理完毕后依旧存活的对象从新整齐的放到一起,使他们之间不留空隙。第二种是标记-清除算法(CMS),即清理完毕之后不再整理,这样做会造成内存随便化,会造成一定程度内存空间的浪费。
CMS 和 Serial Old 可以同时存在。

老年代垃圾回收器种类

CMS、Serial Old(MSC)、Parallel Old

名称出现版本多线程回收算法搭配新生代回收器stop the world其他
Serial Old自JDK诞生标记-整理算法Serial、ParNew、Parallel Scavenge可以搭配CMS
CMS1.5标记-清除算法Serial、ParNew部分不是可搭配Serial Old;分为初始标记(单线程)、并发标记(并发)、重新标记(并行)、并发清除(并发);初始和重新依旧stop the world
Parallel Old1.6并行标记-整理算法Parallel Scavenge

JVM 配置垃圾回收器

查看垃圾回收器

查看 JVM 垃圾回收器类型的三个方式

JVM 指定垃圾回收器

可以看到一个命令就可以搭配指定新生代和老年代的垃圾回收器。
-XX:+UseSerialGC,虚拟机运行在Client模式下的默认值,Serial+Serial Old。
-XX:+UseParNewGC,ParNew+Serial Old,在JDK1.8被废弃,在JDK1.7还可以使用。
-XX:+UseConcMarkSweepGC,ParNew+CMS+Serial Old。
-XX:+UseParallelGC,虚拟机运行在Server模式下的默认值,Parallel Scavenge+Serial Old(PS Mark Sweep)。
-XX:+UseParallelOldGC,Parallel Scavenge+Parallel Old。
-XX:+UseG1GC,G1+G1。
-XX:+UseZGC ,使用 ZGC 垃圾回收器

参考资料

[1]、《深入理解Java虚拟机》
[2]、https://blog.youkuaiyun.com/weixin_39723544/article/details/86693575
[3]、https://blog.youkuaiyun.com/shi2huang/article/details/80085193

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值