这两天被NMS的内存溢出搞得很郁闷,每秒3天的告警也能把NMS弄死,实在很无语。查每个queue,再看put和take的速度。
发现不存在阻塞,然后用每秒100条测试,没有问题,但是程序运行4个小时就是内存溢出。经过询问同事,得到方法,通过jconsole查看内存情况,是不是在上升。结果看到是不断增加。知道最后回收不了。程序出错。但是这个也找不到问题在哪儿。然后就用到了另一个工具JProfiler.
1.jconsole
jdk自带jconsole。
在连接里面点远程,配置一下,就可以连接到linux上面的服务。前提是在Linux里面启动程序的时候有参数:
-Dcom.sun.management.jmxremote -Dcom.sun.managem
ent.jmxremote.port=19002 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
然后在配置窗口里面配置。
完了以后就可以看到了:
2.JProfiler6
1.下载
JProfiler6
http://www.ej-technologies.com/products/jprofiler/overview.html?gclid=CIn3qvHYl6UCFQIjbgodowwPJA
key:L-Larry_Lau@163.com#78484-akisfpr22a5j#268
2.安装和配置
安装:windows下面next安装即可。
Linux下面安装rpm包即可。
配置:
1)Linux: 程序的库里面增加: export LD_LIBRARY_PATH=/usr/local/lib:
/opt/jprofiler6/bin/linux-x86 (
jprofiler6的安装路径
)
在Java的启动项里面增加: -agentpath:/opt/jprofiler6/bin/linux-x86/libjprofilerti.so=port=8849
2)Windows:按照提示创建一个远程应用就可以了。
通过用Jprofiler查看发现有个对象的实例一直在增加,一直到100w,占用空间几十M,原来跟告警没有关系。查看代码发现是有好几个List,在List里面的数据是通过Snmp get到的,应该是这些list不断的增加,而gc没有回收,导致内存耗尽。但是这个程序运行了有好几个月的,都没问题啊,发现有可能是snmp的配置文件用的是默认的,可能取的值比较多,内存溢出的这台服务器上的配置是默认的,没有配,运行几个月的程序是配置好的,然后改了正确的配置后,发现对象的实例不再增加。应该问题就在这儿,所以再跑一段时间看看。
现在存在的疑问: 为什么Java不会去回收List里面的对象呢?还有会不会新增加的进程监控引发内存溢出(这个可以测试)。
看来要对Java的GC有更深入的了解才可以。
二、功能介绍
- 内存剖析 Memory profiler
JProfiler 的内存视图部分可以提供动态的内存使用状况更新视图和显示关于内存分配状况信息的视图。所有的视图都有几个聚集层并且能够显示现有存在的对象和作为垃圾回收的对象。- 所有对象
- 显示类或在状况统计和尺码信息堆上所有对象的包。你可以标记当前值并显示差异值。
- 记录对象 Record objects
- 显示类或所有已记录对象的包。你可以标记出当前值并且显示差异值。
- 分配访问树 Allocation call tree
- 显示一棵请求树或者方法、类、包或对已选择类有带注释的分配信息的J2EE组件。
- 分配热点 Allocation hot spots
- 显示一个列表,包括方法、类、包或分配已选类的J2EE组件。你可以标注当前值并且显示差异值。对于每个热点都可以显示它的跟踪记录树。
- 显示一个列表,包括方法、类、包或分配已选类的J2EE组件。你可以标注当前值并且显示差异值。对于每个热点都可以显示它的跟踪记录树。
- 所有对象
- 堆遍历 Heap walker
在JProfiler的堆遍历器(Heap walker)中,你可以对堆的状况进行快照并且可以通过选择步骤下寻找感兴趣的对象。堆遍历器有五个视图:- 类 Classes
- 显示所有类和它们的实例。
- 分配 Allocations
- 为所有记录对象显示分配树和分配热点。
- 索引 References
- 为单个对象和“显示到垃圾回收根目录的路径”提供索引图的显示功能。还能提供合并输入视图和输出视图的功能。
- 数据 Data
- 为单个对象显示实例和类数据。
- 时间 Time
- 显示一个对已记录对象的解决时间的柱状图。
- 类 Classes
- CPU 剖析 CPU profiler
JProfiler 提供不同的方法来记录访问树以优化性能和细节。线程或者线程组以及线程状况可以被所有的视图选择。所有的视图都可以聚集到方法、类、包或J2EE组件等不同层上。CPU视图部分包括:- 访问树 Call tree
- 显示一个积累的自顶向下的树,树中包含所有在JVM中已记录的访问队列。JDBC,JMS和JNDI服务请求都被注释在请求树中。请求树可以根据Servlet和JSP对URL的不同需要进行拆分。
- 热点 Hot spots
- 显示消耗时间最多的方法的列表。对每个热点都能够显示回溯树。该热点可以按照方法请求,JDBC,JMS和JNDI服务请求以及按照URL请求来进行计算。
- 访问图 Call graph
- 显示一个从已选方法、类、包或J2EE组件开始的访问队列的图。
- 访问树 Call tree
- 线程剖析 Thread profiler
对线程剖析,JProfiler提供以下视图:- 线程历史 Thread history
- 显示一个与线程活动和线程状态在一起的活动时间表。
- 线程监控 Thread monitor
- 显示一个列表,包括所有的活动线程以及它们目前的活动状况。
- 死锁探测图表 Deadlock Detection
- 显示一个包含了所有在JVM里的死锁图表。
- 目前使用的监测器 Current monitor useage
- 显示目前使用的监测器并且包括它们的关联线程。
- 历史检测记录 History usage history
- 显示重大的等待事件和阻塞事件的历史记录。
- 监测使用状态 Monitor usage statistics
- 显示分组监测,线程和监测类的统计监测数据。
- 线程历史 Thread history
- VM 遥感勘测技术 VM telemetry
观察JVM的内部状态,JProfiler提供了不同的遥感勘测视图,如下所示:- 堆 Heap
- 显示一个堆的使用状况和堆尺寸大小活动时间表。
- 记录的对象 Recorded objects
- 显示一张关于活动对象与数组的图表的活动时间表。
- 垃圾回收 Garbage collector
- 显示一张关于垃圾回收活动的活动时间表。
- 类 Classes
- 显示一个与已装载类的图表的活动时间表。
- 线程 Threads
- 显示一个与动态线程图表的活动时间表。
- 堆 Heap