方法一
jmap -histo:live 18311 | head -20 用jmap查看存活的对象情况
定位到代码
现在已经知道了是HashTable的问题,那么就要定位出什么代码引起的
接下来自然要看看是什么代码往HashTable里疯狂的put数据,于是用神器btrace跟踪Hashtable.put调用的堆栈。
首先写btrace脚本TracingHashTable.java:
-
import com.sun.btrace.annotations.*;
-
import static com.sun.btrace.BTraceUtils.*;
-
@BTrace
-
public class TracingHashTable {
-
/*指明要查看的方法,类*/
-
@OnMethod(
-
clazz="java.util.Hashtable",
-
method="put",
-
location=@Location(Kind.RETURN))
-
public static void traceExecute(@Self java.util.Hashtable object){
-
println("调用堆栈!!");
-
jstack();
-
}
-
}
然后运行:
bin/btrace -cp build 4947 TracingHashTable.java
看到有大量类似下图的调用堆栈
可以看出是在接收到消息后查询入库的代码造成的,业务方法调用ibatis再到mysql jdbc驱动执行statement时put了大量的属性到HashTable中。
方法二
jmap命令可以获得运行中的jvm的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等
命令格式
jmap [options] pid -dump:[live,]format=b,file=<filename>
-dump堆到文件,live指明是活着的对象,file指定文件名,pid 是java进程id
通过这个命令可以查看系统内存情况,但受限于所展示的内存通过能够保存到几十兆以上的的文件内容,手工分析查看实在是太过辛苦,所以也未能解决。
jmap -dump:format=b,file=jmap.hprof 32460
在利用Java堆分析工具分析