jmap histo
在实战中定位大内存大对象很难用,而且会 STW,线上没法用。
实际上排查内存用量大的方向,不只是定位对象大小一条:
Arthas Profiler
arthas profiler 命令。profiler start --event alloc
可追踪到代码级别的内存申请量,大部分情况下可以一次性定位到根因。
获取线程级别的内存用量
往往线程级别的用量也会看出很多问题,比如 Tomcat 线程用得少,RocketMQ 用的多,往消费 RocketMQ 的代码瞅瞅基本能知道个大概了。
线程级别内存申请:
GC 飙高的时候通过这个一眼就能看出大部分是消费 appPush 的线程在大量申请内存。
参考代码:
// 注意 ThreadMXBean 是 com.sun.management 不是 java.lang.management
ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
for (long threadId : threadMXBean.getAllThreadIds()) {
long threadAllocatedBytes = threadMXBean.getThreadAllocatedBytes(threadId);
if (threadAllocatedBytes > 0) {
System.out.println("thread " + threadId + ", size:" + FileUtils.byteCountToDisplaySize(threadAllocatedBytes));
}
}