GC Cause解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 通常,在基于Java生态体系中的应用程序抛出异常时,生产环境都会通过gc log[当然,也有2愣子直接去线上环境进行各种骚操作]去捕获各种可疑线索,以便快速、高效定位及解决问题。

通常,在基于Java生态体系中的应用程序抛出异常时,生产环境都会通过gc log[当然,也有2愣子直接去线上环境进行各种骚操作]去捕获各种可疑线索,以便快速、高效定位及解决问题。

      本文主要基于 Hotspot VM 中“CMS”垃圾回收策略的一些实际场景进行汇总,[涉及的基础概念暂不在本章赘述]简要通过部分源码对引起GC现象的根本原因进行分析以及对排查方法进行总结。另外,本文专业术语较多,有一定的阅读门槛,如对JVM体系所涉及的内存分配及垃圾回收没有理论支撑以及实战经验,还请去官网查阅相关材料。

在我们测试环境或者预发布环境,通常通过如下命令查看某一特定Java应用程序的GC详细情况:


[administrator@JavaLangOutOfMemory luga % ]jstat -gccause pid xxxxx

以确认上次GC的原因和当前GC的原因。

     GC Cause,顾名思义,就是引起发生垃圾回收的因素。只有了解是什么原因引起的 GC,以及每次的时间花费情况,才能有效去定位、分析问题所在。但是要具体分析 GC 的问题,首先要读懂 GC Cause,即 JVM在何种场景下选择进行 GC 操作,具体 GC Cause 的分类可参考Hotspot 源码:

       src/share/vm/gc/shared/gcCause.hpp

       src/share/vm/gc/shared/gcCause.cpp


const char* GCCause::to_string(GCCause::Cause cause) {
  switch (cause) {
    case _java_lang_system_gc:
      return "System.gc()";
    case _full_gc_alot:
      return "FullGCAlot";
    case _scavenge_alot:
      return "ScavengeAlot";
    case _allocation_profiler:
      return "Allocation Profiler";
    case _jvmti_force_gc:
      return "JvmtiEnv ForceGarbageCollection";
    case _gc_locker:
      return "GCLocker Initiated GC";
    case _heap_inspection:
      return "Heap Inspection Initiated GC";
    case _heap_dump:
      return "Heap Dump Initiated GC";
    case _wb_young_gc:
      return "WhiteBox Initiated Young GC";
    case _wb_conc_mark:
      return "WhiteBox Initiated Concurrent Mark";
    case _wb_full_gc:
      return "WhiteBox Initiated Full GC";
    case _no_gc:
      return "No GC";
    case _allocation_failure:
      return "Allocation Failure";
    case _tenured_generation_full:
      return "Tenured Generation Full";
    case _metadata_GC_threshold:
      return "Metadata GC Threshold";
    case _metadata_GC_clear_soft_refs:
      return "Metadata GC Clear Soft References";
    case _cms_generation_full:
      return "CMS Generation Full";
    case _cms_initial_mark:
      return "CMS Initial Mark";
    case _cms_final_remark:
      return "CMS Final Remark";
    case _cms_concurrent_mark:
      return "CMS Concurrent Mark";
    case _old_generation_expanded_on_last_scavenge:
      return "Old Generation Expanded On Last Scavenge";
    case _old_generation_too_full_to_scavenge:
      return "Old Generation Too Full To Scavenge";
    case _adaptive_size_policy:
      return "Ergonomics";
    case _g1_inc_collection_pause:
      return "G1 Evacuation Pause";
    case _g1_humongous_allocation:
      return "G1 Humongous Allocation";
    case _dcmd_gc_run:
      return "Diagnostic Command";
    case _last_gc_cause:
      return "ILLEGAL VALUE - last gc cause - ILLEGAL VALUE";
    default:
      return "unknown GCCause";
  }
  ShouldNotReachHere();
}

     结合源码,我们可以看到,在实际的项目中,针对GC此处产生问题的分析重点需要关注的以下几个GC Cause:        

     1、System.gc():即,显性手动触发GC操作        

     2、CMS:CMS GC 在执行过程中的一些动作,重点需要关注 CMS Initial Mark 和 CMS Final Remark 两个 STW 阶段        

     3、Promotion Failure:Old 区没有足够的空间分配给 Young 区晋升的对象(即使总可用内存足够大)        

     4、Concurrent Mode Failure:CMS GC 运行期间,Old 区所预留的空间不足以分配给新创建的对象,此时收集器会发生退化,甚至严重影响 GC 性能        

     5、GCLocker Initiated GC:如果线程执行在 JNI 临界区操作时,刚好需要进行 GC操作,此时 GC Locker 将会阻止 GC 操作的发生,同时阻止其他线程进入 JNI 临界区,直到最后一个线程退出临界区时触发一次 GC        

     在一次实际的业务场景处理的过程中,如何判断是 GC 操作导致的故障,还是应用系统本身引发 GC 问题?这里主要结合相关数据信息(例如:监控数据、GC Log日志文件、资源使用情况以及可获得的HeapDump/ThreadDump及CoreDump等相关转储文件)进行合理分析。围绕“GC 耗时增大、线程 Block 增多、慢查询增多、CPU 负载高“等核心要素,准确定位、判断到底哪个是罪魁祸首。        

     毕竟,不同的根因,后续的分析方法不尽相同。如果是 CPU 负载高,那可能需要用火焰图或者借助Nmon工具结合应用程序看下相关热点;如果是慢查询增多那可能需要观察下 DB 资源情况;如果是线程 Block 引起那可能需要判断是否存在锁竞争的情况;反之,如果各个核心要素证明都没有问题,那么罪魁祸首可能存在于GC这块,So,我们就需要以GC为切入点继续分析 GC 问题,直到将其Fix掉为止。      

     综上所述,只有通过对GC Cause的相关源码以及产生的相关因素进行剖析,在应用程序出现内存问题时才能游刃有余去处理。

相关文章
|
4月前
|
存储 监控 算法
深入解析JVM内部结构及GC机制的实战应用
深入解析JVM内部结构及GC机制的实战应用
|
缓存 算法 Java
JVM CMS GC算法解析
JVM CMS GC算法解析
86 0
|
前端开发 Java
Java虚拟机 CMS GC 调优解析
随着 JDK 版本的不断升级,其 GC 策略也随之不停革新,从早期的 1.4 到如今的 11(本文仅讨论在线上环境落地规模较大的版本),其对应的 GC 策略也随之由 Serial、Parallel、CMS 演进至当前的 G1 甚至即将落地的 ZGC 。每一次的调整无不是基于环境的适配性以及业务场景特性,无论如何,只要能够基于特定的操作系统内核、物理内存、JDK版本以及业务特性,达到收益最大化,采用何种实现策略都不为过。当然,还是建议大家以官方的推荐为准,基于自己的业务场景进行不断优化调整,这样才能保证万无一失,使得我们的业务能够健康发展。
179 0
|
存储 监控 算法
Java虚拟机 G1 GC 调优解析
在上篇文章中,我们解析了 Java 虚拟机体系生态中基于 CMS GC 策略的调优场景及基本案例,具体链接为:Java虚拟机 CMS GC 调优解析。本文则重点介绍另一款当前比较流行的 GC 策略 - G1。
420 0
|
监控 Java Unix
Java GC Log Time解析
通常,我们在了解应用服务的性能时,都会去在所定义的垃圾收集日志文件中去分析GC活动轨迹,在gc.log文件中,我们经常会看到每个GC事件所打印的三种时间类型: “ User ”、“ Sys ”及“ Real ”,它们分别表示什么呢?具有哪些象征性意义呢?本文将结合作者的相关实际经验进行简要解析,希望阅读完本篇文章后对大家在GC Log这块的问题定位与分析有所帮助。
210 0
|
机器学习/深度学习 人工智能 监控
GC日志分析工具-GCeasy解析
一款新的GC日志分析仪器,业界首个基于人工智能机器学习指导的垃圾收集日志分析工具。 GCeasy具有内置的智能功能,可以自动检测JVM和Android GC日志中的问题并为之推荐解决方案。
804 0
|
存储 算法 Java
CMS 触发GC(Allocation Failure)解析
针对GC中发生的"Allocation Failure"
849 0
|
缓存 Oracle Java
53.【面试宝典】面试宝典-jvm参数配置实战-gc日志解析
【面试宝典】面试宝典-jvm参数配置实战-gc日志解析
53.【面试宝典】面试宝典-jvm参数配置实战-gc日志解析
|
缓存 监控 算法
【JVM深度解析】GC与分代回收机制
你真的了解Java的分代收集吗?什么是垃圾呢?垃圾会马上被回收吗?JVM中哪些区域会被回收呢?Java/C++垃圾收集有什么不同?不懂?一文带你搞懂gc基础!
【JVM深度解析】GC与分代回收机制
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2

推荐镜像

更多