You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
如果内存使用率增长的很快,在CMS执行的过程中,已经出现了内存不足的情况,此时CMS回收就会失败,虚拟机将启动老年代串行回收器(Serial Old 收集器)进行垃圾回收,这会导致应用程序中断,直到垃圾回收完成后才会正常工作。这个过程GC的停顿时间可能较长,所以-XX:CMSInitiatingoccupancyFraction的设置要根据实际的情况。
从整体来看是基于「标记-整理」算法实现的收集器,但从局部(两个 Region 之间)上看又是基于「标记-复制」算法实现
G1 即是新生代又是老年代收集器”,无需组合其他收集器。
每个 Region 的大小可以通过参数-XX:G1HeapRegionSize 设定,取值范围为 1MB~32MB,且应为 2 的 N 次幂。而对于那些超过了整个 Region 容量的超级大对象,将会被存放在 N 个连续的 Humongous Region 之中,G1 的大多数行为都把 Humongous Region 作为老年代的一部分来进行看待
G1 收集器 Region 划分:
特性
Region 区域:把连续的 Java 堆划分为多个大小相等的独立 Region,每一个 Region 都可以根据需要,扮演新生代的 Eden 空间、Survivor 空间,或者老年代空间
Humongous 区域:专门用来存储大对象。只要大小超过了一个 Region 容量一半的对象即可判定为大对象。
基于停顿时间模型:消耗在垃圾收集上的时间大概率不超过 N 毫秒的目标(使用参数-XX:MaxGCPauseMillis 指定,默认值是 200 毫秒)
每个 Region 的大小可以通过参数-XX:G1HeapRegionSize 设定,取值范围为 1MB~32MB,且应为 2 的 N 次幂。而对于那些超过了整个 Region 容量的超级大对象,将会被存放在 N 个连续的 Humongous Region 之中,G1 的大多数行为都把 Humongous Region 作为老年代的一部分来进行看待
大致实现步骤
初始标记:仅仅只是标记一下 GC Roots 能直接关联到的对象,并且修改 TAMS 指针的值,让下一阶段用户线程并发运行时,能正确地在可用的 Region 中分配新对象。
需要「Stop The World」,但耗时很短,而且是借用进行 Minor GC 的时候同步完成的。
筛选回收:负责更新 Region 的统计数据,对各个 Region 的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个 Region 构成回收集,然后把决定回收的那一部分 Region 的存活对象复制到空的 Region 中,再清理掉整个旧 Region 的全部空间。需要「Stop The World」,多条收集器线程并行完成。
TAMS 指针简单理解为:G1 为每一个 Region 设计了两个名为 TAMS(Top at Mark Start)的指针,把 Region 中的一部分空间划分出来用于并发回收过程中的新对象分配,并发回收时新分配的对象地址都必须要在这两个指针位置以上
SATB 记录简单理解为:解决并发扫描时对象的消失问题
彻底搞懂JDK11前的7个垃圾收集器
上一篇文章 jvm垃圾回收机制 我们了解了 垃圾回收机制和算法等知识点,今天我们来讲讲jvm最重要的堆内存是如何使用垃圾回收器进行垃圾回收,并且如何使用命令去配置使用这些垃圾回收器。
回收哪些区域的对象
需要注意的是,JVM GC只回收堆内存和方法区内的对象。而栈内存的数据,在超出作用域后会被JVM自动释放掉,所以其不在JVM GC的管理范围内。
垃圾回收器总览
新生代可配置的回收器:Serial、ParNew、Parallel Scavenge
老年代配置的回收器:CMS、Serial Old、Parallel Old
新生代和老年代区域的回收器之间进行连线,说明他们之间可以搭配使用。
如何选择合适的垃圾收集器
垃圾收集器选择场景分析
Serial/Serial Old 收集器
应用场景
ParNew 收集器
Parallel Scavenge/Parallel Old 收集器
特性
两个参数用于精确控制吞吐量,分别是:
-XX:+UseAdaptiveSizePolicy 当这个参数被激活之后,就不需要人工指定新生代的大小(-Xmn)、Eden 与 Survivor 区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等细节参数,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。
使用-XX:+UseParallelGC参数可以设置新生代使用这个并行回收器,即 Parallel Scavenge + Parallel Old。
CMS 回收器
CMS全称为:Concurrent Mark Sweep意为并发标记清除,他使用的是标记清除法。主要关注系统停顿时间。
使用-XX:+UseConcMarkSweepGC 进行设置老年代使用该回收器。
使用-XX:ConcGCThreads设置并发线程数量。
实现步骤
缺点:
应用场景
关注服务的响应速度,希望系统停顿时间尽可能短,以给用户带来良好的交互体验。
特性
CMS不会等到应用程序饱和的时候才去回收垃圾,而是在某一阀值的时候开始回收,回收阀值可用指定的参数进行配置:-XX:CMSInitiatingoccupancyFraction来指定,默认为68,也就是说当老年代的空间使用率达到68%的时候,会执行CMS回收。
如果内存使用率增长的很快,在CMS执行的过程中,已经出现了内存不足的情况,此时CMS回收就会失败,虚拟机将启动老年代串行回收器(Serial Old 收集器)进行垃圾回收,这会导致应用程序中断,直到垃圾回收完成后才会正常工作。这个过程GC的停顿时间可能较长,所以-XX:CMSInitiatingoccupancyFraction的设置要根据实际的情况。
之前我们在学习算法的时候说过,标记清除法有个缺点就是存在内存碎片的问题,那么CMS有个参数设置-XX:+UseCMSCompactAtFullCollecion可以使CMS回收完成之后进行一次碎片整理。
-XX:CMSFullGCsBeforeCompaction参数可以设置进行多少次CMS回收之后,对内存进行一次压缩。
G1 回收器
G1 收集器 Region 划分:
特性
大致实现步骤
需要「Stop The World」,但耗时很短,而且是借用进行 Minor GC 的时候同步完成的。
G1 缺点
G1 应用场景
G1 的首要重点是为运行需要大堆且 GC 延迟有限的应用程序的用户提供解决方案。这意味着堆大小约为 6 GB 或更大,并且稳定且可预测的暂停时间低于 0.5 秒。
如果应用程序具有以下一个或多个特征,那么今天运行 CMS 或并行压缩的应用程序将从切换到 G1 中受益。
G1 最佳实践
1.不要设置年轻代的大小
如果通过 -Xmn 显式地指定了年轻代的大小, 则会干扰到 G1 收集器的默认行为。
G1 在垃圾收集时将不再关心暂停时间指标。所以从本质上说,设置年轻代的大小将禁用暂停时间目标。
G1 在必要时也不能够增加或者缩小年轻代的空间。 因为大小是固定的,所以对更改大小无能为力。
2.响应时间指标
设置 XX:MaxGCPauseMillis=N 时不应该使用平均响应时间 (ART, average response time) 作为指标,而应该考虑使用目标时间的 90% 或者以上作为响应时间指标。也就是说 90% 的用户请求响应时间不会超过预设的目标值。暂停时间只是一个目标,并不能保证总是满足。
3.什么是转移失败 (Evacuation Failure)?
对 Survivors 或晋升对象进行 GC 时如果 JVM 的 Heap 区不足就会发生提升失败。堆内存不能继续扩充,因为已经达到最大值了。
当使用 -XX:+PrintGCDetails 时将会在 GC 日志中显示 to-space overflow。
这是很昂贵的操作!
The text was updated successfully, but these errors were encountered: