内存泄漏是比较常见的一种应用程序性能问题,一旦发生,则系统的可用内存和性能持续下降;最终将导致内存不足(OutOfMemory),系统彻底宕掉,不能响应任何请求,其危害相当严重。同时,Java堆(Heap)中大量的对象以及对象间之复杂关系,导致内存泄漏问题的探测和分析均比较困难,采用相应的辅助工具是很必要的。
我使用的比较多的是Memory Dump Diagnostic for Java (MDD4J)和IBM HeapAnalyzer,这两个工具都能支持几乎所有JDK版本所生成的堆转储文件,使用前可以在两者的帮助文件中查看一下支持列表。
先说一下IBM HeapAnalyzer,下载之后首先阅读一下readme,这上面详细写了HeapAnalyzer的使用方法。对于我用的2.6版本(最新为3.8),可以在命令行中输入<Java path>java –Xmx[heapsize] –jar ha26.jar <heapdump file>来启动工具并加载heapdump文件。对于比较大的heapdump,将-Xmx设置一个较大的值(大于heapdump的大小),来避免加载过程中的OOM。对于64位机器上产生的超大heapdump,个人机器上分析就不大可能了。
打开heapdump文件后,我一般点击“Analysis”里的“Tree View”,以树的形式从根节点展示内存对象分配的信息
第一行java.lang.ref.Refenrence这个class及它的76个children占用了67%的已用堆大小(31M/46M),它本身仅占用了76bits。双击java.lang.ref.Refenrence,我们可以看到它所引用的两个子节点。其中一个子节点java.lang.ref.Finalizer后的67%指引我们内存泄漏的问题应该在它的引用上。
接下去你可以逐级展开,或者右键点击“Locate a leak suspect”,让HeapAnalyzer帮你找到泄漏可能发生的地方。泄漏一般发生在那些拥有“超乎寻常多”的引用(子节点)的class上,正是这些创建后没有释放、累积了成千上百的对象,造成了OutOfMemory。右键中的“Go to the largest drop subtrees”也是以此为原理而设的,它的解释为:
“Search for total size drop” will find a size drop between the total size of a parent and the biggest total size of child of the parent.
因为出现泄漏的点,每个子节点占用的内存空间不大,但是巨大的数量会导致父节点占用的total size很大。不过反过来寻找到的点都是泄漏发生的地方这种说法是不成立的,否则也不需要我们来分析了。
更多细节的内容,可以看这篇PPT
Memory Dump Diagnostic for Java (MDD4J)则是IBM Support Assistant(ISA)里的一个工具,可以在ISA里加载。它的使用方法和HeapAnalyzer类似,不过它会自动列出“可疑泄漏点”供分析。所依据的,是“分析算法查找父对象与子对象之间对象大小的显著变化。这些发生显著变化的父对象可能是基于数组的容器对象,它们包含大量不断增大的子对象。”
具体的使用方法可以参考《WebSphere Application Server 中的内存泄漏检测与分析:第 2 部分:用于泄漏检测与分析的工具和功能》一文中的实际案例。(不过文中的版本应该比较低,现在能下到的2和3版本有些不同,不过不妨碍使用).
Heapdump工具的使用很简单,难点在于找到“内存泄漏的真正原因”,一般需要通过多个heapdump文件的对比才能找到。
比较分析用于对运行内存泄漏应用程序期间(即可用 Java 堆内存流失时)获取的两个内存转储进行分析。在运行泄漏应用程序的早期触发的内存转储被称为基线内存转储,发生泄漏的应用程序运行一段时间(以允许泄漏程度加大)后触发的内存转储被称为主内存转储。在发生了内存泄漏的情况下,主内存转储可能包含大量对象,而这些对象占用的 Java 堆空间量会比基线内存转储大很多。
为了获得更好的分析结果,建议使主内存转储的触发点与基线内存转储的触发点在时间上拉开一定距离,从而使总耗用堆大小在两个触发点之间大幅增长。
如果发现“主内存转储”中的某个对象数量大大大于“基线内存转储”,那么这个对象一般就是发生泄漏的点。但是要避免在appserver刚启动时就做heapdump,否则会把正常需要分配的对象当作泄漏嫌疑点。比如原先运行3天会发生OOM,那么可以:缩小堆大小,让OOM提早发生;在运行4个小时后每隔4小时手动做一次Heapdump直到OOM发生。这些动作也许不适合在生产环境下进行,可以另建测试环境进行。
之前几篇文章中介绍的分析gc log,和本文讲到的分析heapdump,都是脱机分析法。它们的缺陷就是无法找到代码引起的“性能低下”的原因,正如《用HPjtune分析GC日志》里所看到的那样,系统性能很差,但是没有OOM发生,可用堆在每次full gc后还不断减少的现象不能简单怪罪为内存泄漏,毕竟最后都回收下来了,如果手动做heapdump,可能有问题的对象已被回收,无法得到正确的结果。这种情况下要使用诸如Jprofile这样直接附加到JVM上的工具来监测了。
最后附一下手动生成heapdump的方法,免得事到临头在google。
在Linux/AIX环境下
使用Kill -3 pid命令来调用堆转储.
Windows环境下
1. 找到JVM对象名字。
<wsadmin> set objectName [$AdminControl queryNames
WebSphere:type=JVM,process=<servername>,node=<nodename>,*]
2. 对JVM MBean调用generateHeapDump操作。
<wsadmin> $AdminControl invoke $objectName generateHeapDump
如果上述方法是没有生成,那么进行下面的设置。
访问管理控制台
转到“服务器”>“应用程序服务器”> Server1(或者要获取其堆转储的服务器的名称)>“进程定义”>“环境条目”。
单击“新建”。
在“名称”字段中,输入 IBM_HEAPDUMP(默认是开启的)。在“值”字段中,输入 true。
单击“确定”。
重复步骤 3 至 5,但将 IBM_HEAPDUMP_OUTOFMEMORY 设置为 true。
缺省情况下,将在 ~/WebSphere/AppServer/ 目录中创建内存转储(对于 WebSphere Application Server V6.x 而言,缺省目录是:~/WebSphere/AppServer/profiles/default)。要将堆转储目标定向到另一个目录,请转至“环境条目”,单击“新建”,将 IBM_HEAPDUMPDIR 设置为适当的目录(例如 /heapdumps),然后单击“确定”。
单击“保存”,然后在下一个屏幕中再次单击“保存”。
转到“服务器”>“应用程序服务器”> server1(或者要获取其堆转储的服务器的名称)>“进程定义”>“Java 虚拟机”。
选择“详细垃圾回收”。
单击“保存”,然后在下一个屏幕中再次单击“保存”。
重新启动服务器。
打开命令提示符并转至 /WebSphere/AppServer/bin 目录。
通过发出 kill -3 XXXXX 命令来调用堆转储,其中 XXXXX 是进程标识。
如果WebSphere运行在HP-UX上,那么需要
- 访问管理控制台
- 转到“服务器”>“应用程序服务器”> Server1(或者要获取其堆转储的服务器的名称)>“进程定义”>“环境条目”。
- 在“常规参数”中,输入:-Xrunhprof:depth=0,heap=dump,format=a,thread=n,doe=n
- 缺省情况下,将在 ~/Websphere/AppServer/ 目录中创建内存转储。要将堆转储目标定向到另一个目录,请添加 HProf 参数 file=/heapdumpdir/hprof.txt,其中 heapdumpdir 是适当的目录,而 hprof.txt 是适当的文件名。如果创建了多个内存转储,那么将把每个内存转储追加到同一个 hprof.txt 文件中。
- 选中“启用详细垃圾回收方式”。
- 重新启动服务器。
- 通过发出 kill -3 XXXXX 命令创建堆转储,其中 XXXXX 是进程标识。
- 除非另有指定,否则将在 ~/WebSphere/AppServer/ 目录中创建 hprof 转储,并且文件名看起来类似于 java.hprof.txt。
- 关闭应用程序服务器,然后移动 hprof 转储文件。直到正确关闭应用程序服务器之后,hprof 转储文件才完整。
- 注意:请检查是否每个 hprof 转储都包含 HEAP DUMP BEGIN 和 HEAP DUMP END 这两组标记。如果 hprof 转储的这两组标记不齐全,那么表明该转储不完整且不能用于分析
分享到:
相关推荐
j2mod-1.06.jar,支持 Modbus/RTU Modbus/TCP Modbus/ASCII Modbus/UDP Modbus Slave Modbus Master
本文将深入探讨两种在Java环境下操作Modbus协议的方法:jamod和modbus4J库。 首先,让我们来了解jamod。jamod是Java Modbus Toolkit的简称,是一个用Java编写的开源库,专门用于实现Modbus协议。它提供了对TCP和RTU...
总之,Java我的世界城建类MOD是一个利用Java编程语言和Minecraft开发框架制作的扩展,其核心在于提升游戏内的建筑体验,提供多样化的建筑元素和工具,同时通过mtr和附加包增加游戏内容的深度和广度,使玩家能够在...
使用JVisualVM、MAT(Memory Analyzer Tool)等工具进行内存分析,找出内存泄漏的源头。这些工具能帮助识别长时间存活的对象、内存快照对比以及可疑的大对象。 6. **代码优化** - 及时释放不再使用的对象引用,...
概述 该项目是库的一个分支,该库从开始。 除了支持JUnit测试外,还对该库进行了大量的重构和代码修复,以确保该库适合生产使用。 该实现在主站和从站配置中均支持Modbus TCP,UDP,基于TCP的RTU,串行... 包括j2mod
Modbus4J是一个Java库,专门用于处理Modbus通信协议,它为开发人员提供了一种在TCP/IP网络上与支持Modbus协议的设备进行交互的便捷方式。Modbus是一种广泛使用的工业通信协议,允许不同设备之间交换数据,常用于自动...
Modbus4J是一个Java库,专门用于实现Modbus通信协议,这是一个广泛使用的工业协议,用于设备间的数据交换,特别是PLC(可编程逻辑控制器)和其他自动化设备之间。这个工具包为开发者提供了在Java应用程序中轻松集成...
标题“mod(div).rar_DIV_MOD_大数计算 java”暗示我们将探讨的是Java中的大数除法和取模运算,这在某些算法中非常关键。 Java中的大数计算主要通过`java.math.BigInteger`类来实现。这个类提供了一系列方法,用于...
modbustcp协议的读取,已使用该jar包完成一个完整项目
modbus的开发jar包和dll,其中包含modbus4J.jar、modbus4j继电器调试记录.pdf、RXTXcomm.jar、rxtxParallel.dll、rxtxSerial.dll、seroUtils.jar
7. **报表和可视化**:Java的图形用户界面(GUI)库如Swing或JavaFX可以用来创建直观的库存报表和仪表板,帮助管理人员更好地理解和分析库存状况。 8. **异常处理**:Java的异常处理机制保证了程序在遇到错误时能够...
Java_MODBUS_javamodbus_java写的modbus03功能参考_longer4mf_modbus03_mod 是一个关于使用Java实现Modbus协议03功能的项目。Modbus是一种广泛使用的工业通信协议,常用于PLC(可编程逻辑控制器)和其他设备间的通信...
"更多箱子"(Iron Chests)模组,为 Java 版 1.7.10 的 Minecraft 带来了一个强大的解决方案,它极大地增加了游戏中箱子的容量,让你的储物需求不再受限。 "更多箱子"模组,正如其名,为玩家提供了比原版游戏更强大...
支持龙书附录中的部分语法,完成词法匹配、语法分析和中间代码生成如 program sample(a1,b2) var a,b:integer; var c,d:real; begin a:=1; b:=2; a:=b+c3; a:=8+7+6+5+4+3+2+1+9*8 mod 7-6+5+4 div 3; if a* -10-9...
MOD 模特排时法的远离;MOD法的特点;MOD法的动作分类、动作分析;改进和应用
Java有内置的安全模型,可以防止内存泄漏和XSS、SQL注入等攻击,但配置复杂。PHP则依赖于开发者自身的安全意识,通过使用预处理语句、过滤用户输入等方式来保障安全。 总的来说,选择Java还是PHP,取决于项目的具体...
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件...
Java模型和模式是Java开发中的核心概念,它们是软件设计的基石,有助于创建可扩展、可维护和高效的应用程序。本资源"java_model.rar"包含了关于Java模塑和设计模式的详细资料,特别关注了23种经典的GOF(Gang of ...
本文将深入探讨基于Java的课程编辑器AutoDrive mod如何在FS19和FS22这两个版本中运行,并分析其工作原理。 AutoDrive mod的核心功能是自动路径规划和驾驶,它能够帮助玩家自动控制农机具在农田中按照预设路线行驶,...
Java 连接和验证 LDAP 文档 Java 连接和验证 LDAP 文档是一份关于 Java 语言连接和验证 LDAP 服务器的学习文档。LDAP(Lightweight Directory Access Protocol)是一种目录访问协议,用于管理和访问目录服务中的...