捕获Java内存泄露 (三)

原文:Hunting Memory Leaks in Java
上一篇:捕获Java内存泄露 (二)

捕获Java内存泄露 (三)

并非OOM的应用程序崩溃

有时,应用程序可能会在本地堆的分配失败后迅速崩溃。如果你运行不检查由内存分配函数返回的错误的本地代码,则会发生这种情况。

例如,如果没有可用内存,malloc系统调用返回NULL。如果从malloc返回结果没有被检查,那么当应用程序试图访问无效的内存地址时,它可能会崩溃。取决于环境的不同,这种类型的问题可能很难找到。

在某些情况下,从致命错误日志或崩溃时转储记录中给出的信息将是足够的。如果崩溃的原因被确定为在某些内存分配中缺少错误处理,那么你必须查找这次分配失败的原因.。与其他本地堆问题一样,系统可能只配置了不足的交换空间,或者另一个进程正在消耗所有可用的内存资源,等等。

诊断泄漏

在大多数情况下,诊断内存泄漏需要非常深入细节的关于问题应用程序的知识。警告:这个过程可能是冗长和反复的。

我们寻找内存泄漏的策略,将相对直接:

  • 识别症状
  • 启用verbose垃圾收集
  • 启用分析器
  • 分析踪迹

1. 识别症状

如上所述,在许多情况下,java的进程最终会抛出OOM运行时异常,明确的指出你的内存资源已经耗尽。在这种情况下,你需要区分出正常内存耗尽和内存泄漏。分析OOM的信息,基于上述讨论尽力找到它的罪魁祸首。

通常情况下,如果一个java应用程序请求的内存多于运行时堆提供的存储空间,它可以是由于糟糕的设计。例如,如果应用程序创建一个图像的多个副本或加载一个文件到数组中,而图像或文件是非常大的,它会耗尽内存。这是一个正常的资源枯竭。应用程序的工作符合设计(尽管这样的设计显然是愚蠢的)。

但是,如果应用程序在处理同一种数据时,其内存利用率稳步提高,你可能遇到一个内存泄漏。

2. 启用verbose垃圾收集

最快的断定你确实有一个内存泄漏的方法是启用verbose垃圾收集。内存约束的问题通常可以通过分析verbosegc输出模式来识别。

具体而言,-verbosegc参数允许你生成一个对每一次启动垃圾收集(GC)过程的跟踪。也就是说,当内存开始垃圾收集,汇总报告打印到标准错误输出,让你对你的内存是如何管理的有有一个了解。

下面是一些带–verbosegc选项生成的典型的输出:
verbosegc

每一块(或节)在GC跟踪文件中由升序数字编号。为了让跟踪有意义,你应该看看连续分配失败的节和寻找是否有随着时间的推移,被释放的内存(字节数和百分比)在减少,而总的内存消耗(这里是19725304)在增加。这些都是内存耗尽的典型迹象。

3. 启用分析器

不同的jvm提供了不同的方式为生成跟踪文件来反映堆活动,但通常都包括关于对象类型和大小的详细信息。这被称之为heap profiling(堆分析)。

4. 分析踪迹

这篇文章着重于Java VisualVM生成的踪迹。踪迹可以以不同的格式出现,因为它们可以由不同的工具生成,但它们深层的思路总是一致的:在堆中找到一块不应该存在的对象,并确定这些对象是否积累而不释放。特别感兴趣的是临时对象,众所周知,它在每一次java应用程序的某个事件触发时被分配。本应该只存在较少数量的对象实例存在多个,通常表示应用程序问题。

最后,解决内存泄漏需要你彻底审查你的代码。学习对象泄漏的类型会很有帮助,并大大提高调试速度。

下一篇:捕获Java内存泄露 (四)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值