JProfiler进行Java运行时内存分析

原文地址:http://www.javashuo.com/article/p-gtzuxzek-hq.htmlhtml

在最近的工做中,经过JProfiler解决了一个内存泄漏的问题,现将检测的步骤和一些分析记录下来,已备从此遇到类似问题时能够做为参考。tomcat

 

运行环境:

Tomcat6,jdk6,JProfiler8

 

内存泄漏的现象:

1. 在服务器中执行某些批量操做的时候,发现内存只升不降;就算gc后,内存也不能被彻底释放;
2. 除非重启tomcat服务器,内存永远不会被释放,反复执行这些操做,会致使无可用内存,tomcat死掉;

 

使用JProfiler检查内存泄漏的步骤:

1. 初始化检验环境:

切换到“Live Memory-->All Objects”标签,能够看到当前tomcat中的对象状况,注意jprofiler其余版本可能位置不同.服务器

在执行操做前,须要先F4,运行“Run GC”,使jvm进行内存回收清理无效的对象.为了便于比较内存的增加状况,能够点击右键--->"Mark Current",jvm

来将当前内存使用状况做为参照;点击后会显示“Difference”列,该列会列出对象数量的变化和变化比率工具

2.打开内存记录: 

点击“Start Recordings”按钮,开始记录。执行这步的主要目的是为下面“Heap Walker”设置一个监控区间;若是不记录的话“Heap Walker”将分析jvm虚拟机的全部内存,即耗时又不能准确的发现内存泄漏的缘由。spa

3. 执行操做,执行gc;

 使用压力工具访问被测应用,执行完以后再次F4进行GC----这样是为了消除能够回收的对象。执行内存回收后,仍然存在于内存中的对象有多是泄漏的对象。以下图instance count中红色的部门为不能回收的对象,difference列列出了增长的对象数量和增。以String为例,在该操做中增长了31751个对象增幅达到了14%,随后会在HeapWalker中观察这些对象,分析哪些对象是泄漏的。通常引发泄漏的对象包括:String、char[]、HashMap、Concurrenthashmap等,这类对象须要重点关注下;

4. 关闭内存记录:

点击“Stop Recordings”关闭内存记录,告诉jProfiler把这段记录做为分析对象;

5. 找到增长迅速的对象类型,打开HeapWalker:

在视图中找到增加快速的对象类型,本例Concurrenthashmap的增加速度很快。在memory视图中找到Concurrenthashmap---点右键----选择“Show Selectiion In Heap Walker”,切换到HeapWarker 视图;切换前会弹出选项页面,注意必定要选择“Select recorded  objects”,这样Heap Walker会在刚刚的那段记录中进行分析;不然,会分析tomcat的全部内存对象,这样既耗时又不许确;htm

6. 在HeapWalker中,找到泄漏的对象;

HeapWarker 会分析内存中的全部对象,包括对象的引用、建立、大小和数量;
 
HeapWarker视图下方能够进行页面切换:

经过切换到References页签,能够看到这个类的具体对象实例。对象

 为了在这些内存对象中,找到泄漏的对象(应该被回收),能够在该对象上点击右键,选择“Use Selected Instances”缩小对象范围;blog

单击OK按钮内存

7. 经过引用分析该对象:

在References引用页签中,能够看到该对象的的引用关系,能够切换incoming/outcoming,显示引用的类型:

incoming  表示显示这个对象被谁引用;

outcoming 表示显示这个对象引用的其余对象;

 

选择“Show In Graph”将引用关系使用图形方式展示;
选中该对象,点击“Show Paths To GC Root”,会找到引用的根节点;
在上图中,咱们能够发现,这个HashMap Segment对象最终的引用是在ConcurrentHashMap和ReentranLock对象中;

8. 经过建立分析该对象:

若是第7步还不能定位内存泄露的地方,咱们能够尝试使用Allocations页签,该页签显示对象是如何建立出来的;
咱们能够从建立方法开始检查,检查全部用到该对象的地方,直到找到泄漏位置;
相关文章
相关标签/搜索