当前位置:

首页 > 编程开发 > 如何解决Java内存异常导致频繁Full GC的问题?

如何解决Java内存异常导致频繁Full GC的问题?

问题系统日常巡检发现,应用线上出现频繁fullgc现象应用线上出现频繁fullgc排查过程分析dump拉dump文件:小插曲:dump时如果指定:live,则在dump前jvm会先进行一次fullgc,并且gclog里会打印dumpfullgc,这种对非内存泄漏导致的线上异常内存情况排查反而会带来不便,导致我们多dump了好几次。分析dump文件:a.发现大量long[]数组占用最大空间,有异常情况b.查看gc根节点,发现这些long[]数据大部分是被org.HdrHistogram.Histogram持

本文目录

    问题系统

    日常巡检发现,应用线上出现频繁full gc

    现象

    应用线上出现频繁full gc


    如何解决Java内存异常导致频繁Full GC的问题?

    排查过程

    分析dump

    拉dump文件:小插曲:dump时如果指定:live,则在dump前jvm会先进行一次full gc,并且gc log里会打印dump full gc,这种对非内存泄漏导致的线上异常内存情况排查反而会带来不便,导致我们多dump了好几次。

    分析dump文件:

    a. 发现大量long[]数组占用最大空间,有异常情况


    如何解决Java内存异常导致频繁Full GC的问题?

    b. 查看gc根节点,发现这些long[]数据大部分是被org.HdrHistogram.Histogram持有,每个Histogram对象会持有一个2048size的long[]

    c. 查看Histogram实例的数量,竟然有5w个,对比下正常项目的堆栈,大约是100倍


    如何解决Java内存异常导致频繁Full GC的问题?

    d. 这里又有一个插曲,一开始习惯用mat分析,但是mat生成的报告对分析泄露比较有用,对于分析异常的内存没有jvisualvm.exe和idea的profiler好用

    排查原因

    本地启动,可以复现这个类的内存使用情况,于是本地起一个其他内存正常的服务与有问题的应用,分析内存对比

    这里用的是idea的profiler,很方便

    发现差异:

    对比正常的应用,发现异常应用的引用存在异常的来自
    如何解决Java内存异常导致频繁Full GC的问题?
    如何解决Java内存异常导致频繁Full GC的问题?

    ● rx.internal.operators.OnSubscribeReduceSeed$ReduceSeedSubscriber的引用,怀疑就是这个异常引用就是导致这些实例无法在新生代回收而是堆积到了老年代触发full gc的原因

    排查差异:

    简单看了下相关代码,看不出个所以然,直接debug对比

    系统确实走进了相关的代码,增加了对Histogram的引用,而正常应用没有
    如何解决Java内存异常导致频繁Full GC的问题?

    但是光这样也看不出来为什么,此时关注到了左下角的线程池,这个线程池比较奇怪,是Metric的线程池
    Metric是Hystrix用来统计相关指标,来供自己的dashboard或者用户来获取,以此来了解系统熔断相关参数和指标的功能
    再看堆栈,走到这里的逻辑是


    如何解决Java内存异常导致频繁Full GC的问题?

    这个流用来统计单位时间内的系统指标,导致Hystrix使用Histogram的long数组实现类似滑动窗口的效果统计单位时间内的指标
    Histogram本身是Hystrix用来实现类似桶+滑动窗口的功能,来统计单位时间内的流量,但是因为开启了指标参数,导致hystrix为了统计更长时间范围内的指标,新增了对象持有更多(单位时间内)的Histogram引用来聚合,这部分引用因为是统计更长时间范围周期的,就会因为引用持有时间长而到老年代,但是本质并不是内存泄漏,所以每次full gc后又可以得到回收

    解决问题

    看到上面的差异和怪异的线程池,第一反应就是关闭metric使应用不走到这段逻辑中增加引用,看官方文档,该配置默认是打开的,并且确认该功能只影响指标统计不影响断路器本身功能,使用配置hystrix.metrics.enabled=false配置来关闭
    新增配置后,验证并查看堆栈,引用恢复正常,并且系统在一段时间后并没有新增更多的Histogram实例,发布线上后观察一段时间,full gc问题确实得到解决

    根本原因

    在当时发现解决的办法并验证后,并没有时间去研究hystrix.metrics.enabled默认配置就是true但是其他应用没有出现这个full gc问题的原因, 先解决了之后后续再继续跟进排查根本原因防止其他项目也出现相同问题

    之前发现可疑的线程池是HystrixMetricsPoller ,经过查看,该线程池由HystrixMetricsPollerConfiguration


    如何解决Java内存异常导致频繁Full GC的问题?

    类开启,主要依靠hystrix.metrics.enabled开启,但是默认是true,为什么其他项目没有开启呢?

    搜了下源码,这个类的开启还和一个注解有关


    如何解决Java内存异常导致频繁Full GC的问题?

    对比了一下代码,果然只有异常的应用使用了这个注解,这个注解的目的是开启断路器

    但是研究之后发现,不使用这个注解,熔断等功能依旧可用,原因是在spring-cloud高版本之后,spring通过使用hystrix封装openfeign的方法来使用熔断,而不是集成整个hystrix体系,可能spring-cloud也发现了hystrix内存使用上的问题

    所以在较高版本(起码我们的版本),feign是通过feign.hystrix.enabled来开关断路器的(这个开关是关闭的话,单纯加@EnableCircuitBreaker注解断路器是不会生效的)

    其实在更高点版本的spring-cloud中,@EnableCircuitBreaker这个注解已经被标注为废弃了,但是可能因为我们是中间版本,所以存在既没有标注废弃其实又没有什么用的情况

    总而言之,feign的断路功能只通过feign.hystrix.enabled来控制,增加@EnableCircuitBreaker注解之后仅仅只是会开启Hystrix其他所有的指标等功能


    如何解决Java内存异常导致频繁Full GC的问题?

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。