2024-4-23 群讨论:Java堆空间OutOfMemoryError该怎么办

news/2024/12/23 3:37:43/

以下来自本人拉的一个关于 Java 技术的讨论群。关注公众号:hashcon,私信进群拉你

1. 为什么不建议打开 HeapDumpOnOutOfMemoryError?

1.1. 打开 HeapDumpOnOutOfMemoryError,哪些 OutOfMemoryError 会触发 HeapDumpOnOutOfMemoryError?

打开 HeapDumpOnOutOfMemoryError 之后,不是所有的 OutOfMemoryError 都会触发 HeapDumpOnOutOfMemoryError,不同的 OutOfMemoryError 包括(如果对这些异常抛出的原理详情感兴趣,请参考:https://zhuanlan.zhihu.com/p/265039643 ):

  1. OutOfMemoryError: Java heap space 和 OutOfMemoryError: GC overhead limit exceeded:这两个都是 Java 对象堆内存不够了,一个是分配的时候发现剩余空间不足,一个是到达某一界限。这两个都会触发 HeapDumpOnOutOfMemoryError
  2. OutOfMemoryError: unable to create native thread:无法创建新的平台线程,这个不会触发 HeapDumpOnOutOfMemoryError
  3. OutOfMemoryError: Requested array size exceeds VM limit:当申请的数组大小超过堆内存限制,就会抛出这个异常。这个会触发 HeapDumpOnOutOfMemoryError
  4. OutOfMemoryError: Compressed class space 和 OutOfMemoryError: Metaspace:这两个都和元空间相关(底层原理说明参考:https://juejin.cn/post/7225879724545835045 ),这两个都会触发 HeapDumpOnOutOfMemoryError
  5. OutOfMemoryError: Cannot reserve xxx bytes of direct buffer memory (allocated: xxx, limit: xxx):在 DirectByteBuffer 中,首先向 Bits 类申请额度,Bits 类有一个全局的 totalCapacity 变量,记录着全部 DirectByteBuffer 的总大小,每次申请,都先看看是否超限,可用 -XX:MaxDirectMemorySize 限制。这个不会触发 HeapDumpOnOutOfMemoryError
  6. OutOfMemoryError: map failed:这个是 File MMAP(文件映射内存)时,如果系统内存不足,就会抛出这个异常。这个不会触发 HeapDumpOnOutOfMemoryError

还有一些其他的:

  1. Shenandoah 分配区域位图,内存的时候,触发的 OutOfMemoryError,这个会触发 HeapDumpOnOutOfMemoryError
  2. OutOfMemoryError: Native heap allocation failed,这个 Message 可能不同操作系统不一样,但是一般都有 native heap。这个就和 Java 对象堆一般没关系,而是其他块内存无法申请导致的,这些不会触发HeapDumpOnOutOfMemoryError

1.2. 为什么不打开 HeapDumpOnOutOfMemoryError?

HeapDumpOnOutOfMemoryError 的原理:

  1. 进入安全点,所有应用线程暂停,针对 HeapDumpOnOutOfMemoryError,单线程(如果是 jcmd jmap 可以多线程)dump 堆为线程个数个文件。退出安全点。
  2. 将上面的多个文件,合并为一个,压缩。

这里的瓶颈主要在于第一步写入,并且,主要瓶颈再磁盘 IO,我们来看下现在云服务的磁盘 IO 标准:

  1. AWS EFS(普通存储):https://docs.aws.amazon.com/efs/latest/ug/performance.html
  2. AWS EBS(对标 SSD):https://docs.aws.amazon.com/ebs/latest/userguide/ebs-volume-types.html

对于一个 4G 大小的堆内存,如果是 EFS,对标的应该是 100G 以内的磁盘,写入最少也需要大概 4 * 1024 / 300 = 13.65 秒(注意,这个是峰值性能),如果当时峰值性能被用完了,那么需要:4 * 1024 / 15 = 273 秒。如果用 EBS,那么也需要 4 * 1024 / 1000 = 4 秒。注意,这个计算的时间,是应用线程个完全处于安全点(即 Stop-the-world)的时间,还没有还是没考虑一个机器上部署多个容器实例的情况,考虑成本我们也不能堆每个微服务都使用 AWS EBS 这种(对标 SSD)。

所以,建议还是不要打开 HeapDumpOnOutOfMemoryError

2. 不使用 HeapDumpOnOutOfMemoryError 用什么?

2.1. 定位内存泄漏问题靠 JFR

我这边定位 OutOfMemoryError 一般通过 JFR 的 Object Allocation Sample 以及 Old Object Sample 里面的对象去定位,只有这些都定位不出来,才会考虑 Heap Dump。

2.2. 为什么抛出 OutOfMemoryError 的微服务最好下线重启?

因为包括 JDK 的源码在内,都没有在每一个分配内存的代码的地方考虑会出现 OutOfMemoryError,这样会导致代码状态不一致,例如 hashmap 的 rehash,如果里面某行抛出 OutOfMemoryError,前面更新的状态就不对了。还有其他很多库,就不用说了,都很少有 catch Throwable 的,大部分是 catch Exception 的。并且,在每一个分配内存的代码的地方考虑会出现 OutOfMemoryError 也是不现实的,所以为了防止 OutOfMemoryError 带来意想不到的一致性问题,还是下线重启比较好。

2.3. 如何实现抛出 OutOfMemoryError 的微服务下线重启?

一般通过 -XX:OnOutOfMemoryError="/path/to/script.sh"指定脚本,脚本执行:

  1. 微服务的下线
  2. 微服务的重启

针对 spring boot,可以考虑开启允许本地访问 /actuator/shutdown 来关闭微服务(有群友反应抛出 OutOfMemoryError 的时候调用这个会卡死,这是因为 1.2 说的原因,你可能开启了 HeapDumpOnOutOfMemoryError 导致的️),k8s 会自动拉起一个新的。

个人简介:个人业余研究了 AI LLM 微调与 RAG,目前成果是微调了三个模型:

  1. 一个模型是基于 whisper 模型的微调,使用我原来做的精翻的视频按照语句段落切分的片段,并尝试按照方言类别,以及技术类别分别尝试微调的成果。用于视频字幕识别。
  2. 一个模型是基于 Mistral Large 的模型的微调,识别提取视频课件的片段,辅以实际的课件文字进行识别微调。用于识别课件的片段。
  3. 最后一个模型是基于 Claude 3 的模型微调,使用我之前制作的翻译字幕,与 AWS、Go 社区、CNCF 生态里面的官方英文文档以及中文文档作为语料,按照内容段交叉拆分,进行微调,用于字幕翻译。

目前,准确率已经非常高了。大家如果有想要我制作的视频,欢迎关注留言。

本人也是开源代码爱好者,贡献过很多项目的源码(Mycat 和 Java JFRUnit 的核心贡献者,贡献过 OpenJDK,Spring,Spring Cloud,Apache Bookkeeper,Apache RocketMQ,Ribbon,Lettuce、 SocketIO、Langchain4j 等项目 ),同时也是深度技术迷,编写过很多硬核的原理分析系列(JVM)。本人也有一个 Java 技术交流群,感兴趣的欢迎关注。

另外,一如即往的是,全网的所有收益,都会捐赠给希望工程,坚持靠爱与兴趣发电。



http://www.ppmy.cn/news/1434682.html

相关文章

用于车载T-BOX汽车级的RA8900CE

用于车载T-BOX等高精度计时的汽车级时钟模块RTC:RA8900CE.车载实时时钟芯片RA8900CE内置32.768Khz的晶体,实现年、月、日、星期、小时、分钟和秒精准计时。RA8900CE满足AEC-Q200认证,内置温补功能,保证实时时钟的稳定可靠,功耗低至…

vue+element作用域插槽

作用域插槽的样式由父组件决定&#xff0c;内容却由子组件控制。 在el-table使用作用域插槽 <el-table><el-table-column slot-scope" { row, column, $index }"></el-table-column> </el-table>在el-tree使用作用域插槽 <el-tree>…

毫米波雷达模块在高精度人体姿态识别的应用

人体姿态识别是计算机视觉领域中的重要问题之一&#xff0c;具有广泛的应用前景&#xff0c;如智能安防、虚拟现实、医疗辅助等。毫米波雷达技术作为一种无需直接接触目标就能实现高精度探测的感知技术&#xff0c;在人体姿态识别领域具有独特的优势。本文将探讨毫米波雷达模块…

记录一个hive中跑insert语句说没创建spark客户端的问题

【背景说明】 我目前搭建离线数仓&#xff0c;并将hive的执行引擎改成了Spark&#xff0c;在将ods层的数据装载到dim层&#xff0c;执行insert语句时报如下错误 【报错】 [42000][40000] Error while compiling statement: FAILED: SemanticException Failed to get a spark…

Echarts异步数据与动画加载

目录 简介 头部代码 这段代码是使用 Echarts 绘制图表的关键部分。首先&#xff0c;初始化了一个 Echarts 实例。然后&#xff0c;通过 Ajax 请求获取数据&#xff0c;并基于此设置图表选项。其中包括颜色、背景色、标题、提示框、图例以及饼图的具体配置。 具体解释如下&a…

《智能前沿:应对ChatGPT算力挑战》

在全球人工智能热潮中&#xff0c;以 ChatGPT 为代表的 AIGC 技术引发了广泛关注。人工智能和机器学习等技术对数据规模及处理速度等提出了更高要求。在数据成为主要生产要素的当下和未来&#xff0c;如何跟上时代的发展步伐&#xff0c;构建适应 AI 需求的数据中心&#xff0c…

学习c语音的自我感受

因为是自学&#xff0c;所以走过不少弯路。去年&#xff0c;受知乎“python性能弱”风潮的影响&#xff0c;学过go,rust。 在学习这些新语言的时候&#xff0c;由衷感受到&#xff0c;或是本身侧重方向的原因&#xff08;如go侧重服务器&#xff09;&#xff0c;或是语言太新不…

使用Python Tkinter创建文件生成工具

我们将使用Python的Tkinter模块创建一个简单的文件生成工具。这个工具可以用来创建Excel、文本、Python脚本和Word文档等不同类型的文件。 1、准备工作 首先&#xff0c;确保你已经安装了Python和所需的第三方库&#xff1a;Tkinter、openpyxl和python-docx。你可以使用pip来…