GC算法基础概念
GC算法的基础概念#
Card Table#
- 由于做YGC时,需要扫描整个OLD区,效率非常低,所以JVM设计了CardTable
- 如果一个OLD区CardTable中有对象指向Y区,就将它设为Dirty,下次扫描时,只需要扫描Dirty Card
- 在结构上,Card Table用BitMap来实现
CMS#
CMS的问题#
Memory Fragmentation#
- -XX:+UseCMSCompactAtFullCollection
- -XX:CMSFullGCsBeforeCompaction 默认为0 指的是经过多少次FGC才进行压缩
Floating Garbage#
Concurrent Mode Failure #
产生:
if the concurrent collector is unable to finish reclaiming the unreachable objects before the tenured generation fills up,
or if an allocation cannot be satisfiedwith the available free space blocks in the tenured generation,
then theapplication is paused and the collection is completed with all the applicationthreads stopped
解决方案:降低触发CMS的阈值 #
PromotionFailed
解决方案类似,保持老年代有足够的空间
- –XX:CMSInitiatingOccupancyFraction 92% 可以降低这个值,让CMS保持老年代足够的空间
CMS日志分析#
执行命令
java -Xms20M -Xmx20M -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC com.test.jvm.gc.T15_FullGC_Problem01
- [GC (Allocation Failure)
- [ParNew: 6144K->640K(6144K), 0.0265885 secs] 6585K->2770K(19840K), 0.0268035 secs]
- [Times: user=0.02 sys=0.00, real=0.02 secs]
ParNew:年轻代收集器#
- 6144->640:收集前后的对比
- (6144):整个年轻代容量
- 6585 -> 2770:整个堆的情况
- (19840):整个堆大小
[GC (CMS Initial Mark) [1 CMS-initial-mark: 8511K(13696K)] 9866K(19840K), 0.0040321 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] //8511 (13696) : 老年代使用(最大) //9866 (19840) : 整个堆使用(最大) [CMS-concurrent-mark-start] [CMS-concurrent-mark: 0.018/0.018 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] //这里的时间意义不大,因为是并发执行 [CMS-concurrent-preclean-start] [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] //标记Card为Dirty,也称为Card Marking [GC (CMS Final Remark) [YG occupancy: 1597 K (6144 K)][Rescan (parallel) , 0.0008396 secs][weak refs processing, 0.0000138 secs][class unloading, 0.0005404 secs][scrub symbol table, 0.0006169 secs][scrub string table, 0.0004903 secs][1 CMS-remark: 8511K(13696K)] 10108K(19840K), 0.0039567 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] //STW阶段,YG occupancy:年轻代占用及容量 //[Rescan (parallel):STW下的存活对象标记 //weak refs processing: 弱引用处理 //class unloading: 卸载用不到的class //scrub symbol(string) table: //cleaning up symbol and string tables which hold class-level metadata and //internalized string respectively //CMS-remark: 8511K(13696K): 阶段过后的老年代占用及容量 //10108K(19840K): 阶段过后的堆占用及容量 [CMS-concurrent-sweep-start] [CMS-concurrent-sweep: 0.005/0.005 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] //标记已经完成,进行并发清理 [CMS-concurrent-reset-start] [CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] //重置内部结构,为下次GC做准备
1.6之前ps+po,1.6,1.7可以用cms,1.8及以后用G1#
G1(JDK1.8版本开始成熟)#
官方地址:https://www.oracle.com/technical-resources/articles/java/g1gc.html
G1日志详解 #
G1有一个参数,MaxGCPauseMillis -- 建议暂停时间
G1由各种region组成,为了达到建议暂停时间,G1会自动调整Y区大小,来接近这个建议值
使用G1GC
java -Xms20M -Xmx20M -XX:+PrintGCDetails -XX:+UseG1GC com.test.jvm.gc.T15_FullGC_Problem01
G1日志#
- G1的调整目标,尽量不要FGC
- 正常情况下,不会FGC
- 如果FGC时,Heap没怎么变化,一定有OOm
[GC pause (G1 Evacuation Pause) (young) (initial-mark), 0.0015790 secs] //young -> 年轻代 Evacuation-> 复制存活对象 //initial-mark 混合回收的阶段,这里是YGC混合老年代回收(mixedGC) [Parallel Time: 1.5 ms, GC Workers: 1] //一个GC线程 [GC Worker Start (ms): 92635.7] [Ext Root Scanning (ms): 1.1] [Update RS (ms): 0.0] [Processed Buffers: 1] [Scan RS (ms): 0.0] [Code Root Scanning (ms): 0.0] [Object Copy (ms): 0.1] [Termination (ms): 0.0] [Termination Attempts: 1] [GC Worker Other (ms): 0.0] [GC Worker Total (ms): 1.2] [GC Worker End (ms): 92636.9] [Code Root Fixup: 0.0 ms] [Code Root Purge: 0.0 ms] [Clear CT: 0.0 ms] [Other: 0.1 ms] [Choose CSet: 0.0 ms] [Ref Proc: 0.0 ms] [Ref Enq: 0.0 ms] [Redirty Cards: 0.0 ms] [Humongous Register: 0.0 ms] [Humongous Reclaim: 0.0 ms] [Free CSet: 0.0 ms] [Eden: 0.0B(1024.0K)->0.0B(1024.0K) Survivors: 0.0B->0.0B Heap: 18.8M(20.0M)->18.8M(20.0M)] [Times: user=0.00 sys=0.00, real=0.00 secs] //以下是混合回收其他阶段 [GC concurrent-root-region-scan-start] [GC concurrent-root-region-scan-end, 0.0000078 secs] [GC concurrent-mark-start] //无法evacuation,进行FGC [Full GC (Allocation Failure) 18M->18M(20M), 0.0719656 secs] [Eden: 0.0B(1024.0K)->0.0B(1024.0K) Survivors: 0.0B->0.0B Heap: 18.8M(20.0M)->18.8M(20.0M)], [Metaspace: 38 76K->3876K(1056768K)] [Times: user=0.07 sys=0.00, real=0.07 secs]
作者:BigBender
出处:https://www.cnblogs.com/BigBender/p/14422069.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!