记一次Java内存溢出导致程序宕机的问题及排查

文章描述了一次Java程序因内存溢出导致宕机的经历,作者通过本地测试和RuntimeAPI监控内存使用情况,发现问题出在文件转换过程中。文件上传和转换前后内存占用的变化揭示了优化空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Hi, I’m Shendi


记一次Java内存溢出导致程序宕机的问题及排查




问题场景

今天在使用工具中的 word 转 pdf 出了问题,报502错误,打开服务器发现服务被关闭了,起初以为是误关,打开后重新转换又出现了这个问题,在项目文件夹下多了几个文件,打开才知道是因为内存溢出导致程序宕机了。

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

对于这个问题,起初以为是上传文件导致的内存溢出,因为我服务器上内存只剩下几百兆了,而上传的文件近30MB,于是决定在本地测试一下,通过测试得知是转换部分的问题。



排查

对于我的这种情况还是比较好排查的,因为是我自己操作发现的。已经定位到了是哪个具体的接口出了问题

于是只需要在本地进行测试就可以了,通过代码检查内存

对于代码获取内存信息,需要用到 Runtime 的三个函数

  • totalMemory() - 当前占用的内存大小
  • freeMemory() - 未使用的内存大小(占用但还没有使用)
  • maxMemory() - 最大内存大小

通过打印输出,查看内存变化,定位问题的具体代码。

System.out.println("最大可用内存:" + Runtime.getRuntime().maxMemory());
System.out.println("当前内存:" + Runtime.getRuntime().totalMemory() + ", 未用内存: " + Runtime.getRuntime().freeMemory());

我在接口的开始,结束处,以及可能对内存有较大影响的地方都增加打印,因为接口开始即文件上传完成,所以最大的可能性是在转换的地方。

输出如下

// 接口开始 2020MB
最大可用内存:2118123520
// 49MB,31MB
当前内存:51380224, 未用内存: 33082008

// 转换前 --这里创建了输入输出流,以及拿到接口文件的数据 MultipartFile.getBytes()
// 117MB,68MB
当前内存:122683392, 未用内存: 71812848

// 转换后
// 2020MB,656MB
当前内存:2118123520, 未用内存: 688338112

由上面的数据可以分析出来,问题就是出在了转换上,转换将内存吃满了,这还是我本地调试。

以及在转换前,MultipartFile.getBytes() 拿到文件数据并通过这个数据创建输入流的操作也吃了一大内存,文件只是近30MB。还有很大的优化空间




END

### Java服务宕机原因分析与解决办法 #### 1. 排查思路概述 当Java服务出现宕机情况时,可以从多个角度进行排查。通常涉及硬件资源、软件配置以及应用程序本身的逻辑错误等问题。对于服务器频繁宕机的情况,可以按照一定的流程逐步缩小问题范围并最终定位根本原因[^1]。 #### 2. 利用日志信息初步判断 通过查看应用的日志文件,特别是异常堆栈跟踪(Stack Trace),往往能快速获得关于崩溃的第一手线索。如果日志中存在大量超时警告,则可能意味着某些外部依赖的服务响应缓慢甚至不可达;而内存不足或GC频率过高则可能是由于永久代溢出所引起的[^3]。 #### 3. 分析JavaCore及HeapDump文件 一旦发生严重错误导致JVM终止工作,在特定条件下会自动生成名为`JavaCore`和`HeapDump`的诊断文件。前者包含了当时所有正在执行中的线程及其状态快照,后者则是整个堆空间的数据镜像。借助这些资料可以帮助深入理解程序内部的工作状况,并找出潜在的问题所在[^2]。 #### 4. 关注垃圾回收行为 针对由永久代满载引发的应用停止运作案例,应当特别留意Garbage Collection (GC) 的表现模式。可以通过调整JVM参数优化GC策略,比如增加PermGen区域大小或者启用G1收集器等措施缓解此类故障的发生几率[^4]。 #### 5. 考虑并发编程方面的影响 多线程环境下容易产生诸如死锁(deadlock)、竞争条件(race condition)之类的同步难题。若怀疑是因为线程间协作不当造成的系统挂起现象,则建议采用专业的调试工具如VisualVM来进行实时监控,同时仔细审查源码确保临界区得到有效保护[^5]。 ```bash jmap -dump:live,format=b,file=heap.hprof <pid> ``` 上述命令可用于生成指定进程中存活对象组成的二进制格式转储文件,便于后续离线分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HackShendi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值