大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全家桶1年46,售后保障稳定
java有NativeMemoryTracking帮助我们查看jvm带来的内存分配问题,这个只能看jvm带来的,如果是jni的调用申请的内存,那这个工具是没有用的。那大家可能疑惑了,那这个工具也没想象的那么有用,java各种分区,堆的,非堆的,还有直接内存的值jmx都有,想排查是否是jvm带来的似乎也可以做到。那NativeMemoryTracking的作用是什么呢?
对比现有的工具
查看内存数据的工具其实很多,我们通过NativeMemoryTracking和他们进行一下比较。
jstat
NativeMemoryTracking
jmx是否支持命令行观察
支持
支持
不支持
是否支持直接内存
不支持
支持
支持
是否支持unsafe的分配
不支持
支持
不支持
对比的最后一项,很多人可能就要提出疑问,直接内存不就是利用unsafe分配的吗,那这里怎么还写了jmx不支持呢。
直接内存的使用其实是DirectByteBuffer自己维护的内存计数。也就是这个直接内存的数据其实是java code自己维护出来的,只要跳过这些,直接拿他的底层实现方式unsafe.allocateMemory(size);那这个数据是不会被直接内存统计到的,但是nmt可以。
对比之下,我们可以了解nmt的功能和优势,他提供了一种,非图形化界面,而且可以和top配合,快速区分内存占用的到底是谁的问题,如果nmt的数据没有增长,但是top的res涨了说明大概率是jni的调用导致的,如果是jvm的内存增长,我们可以通过detail来查看。
上手使用nmt
我们就拿一个直接内存的demo测试。
public class Malloc {
public static void main(String[] args) {
new Thread(()->{
int i=0;
List s= new LinkedList();
while (i<10){
ByteBuffer buffer = ByteBuffer.allocateDirect(1024*1024*100);
s.add(buffer);
System.out.println(“malloc”);
i++;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{
int i=0;
while (i<10){
byte[] bytes =new byte[1024*1024*10];
}
}).start();
}
}
启动nmt功能。
-XX:NativeMemoryTracking=detail
开启baseline功能。
jcmd pid VM.native_memory baseline
开启了baseline,我们可以更直观的看到数据增长,打印出的数据会有+号。
我们先查看summary信息,先看看谁在增长
jcmd pid VM.native_memory summary.diff
(malloc=123KB #536 +1)
(mmap: reserved=249600KB, committed=2536KB)
– GC (reserved=165933KB, committed=155689KB)
(malloc=12689KB #138)
(mmap: reserved=153244KB, committed=143000KB)
– Compiler (reserved=133KB, committed=133KB)
(malloc=2KB #32)
(arena=131KB #7)
– Internal (reserved=1035599KB +307200KB, committed=1035599KB +307200KB)
(malloc=1035567KB +307200KB #2102 +3)
(mmap: reserved=32KB, committed=32KB)
目前测试使用的是java8,用unsafe申请的内存会在Internal中。
然后使用detail.diff来查看到底是谁导致的。
我们依据summary的分区的数据,找到我们关注的是Internal。然后基于这个再看diff
[0x000000010cf8638b] Unsafe_AllocateMemory+0x78
[0x0000000110d99667]
(malloc=1024000KB type=Internal +307200KB #10 +3)
这里我们就只看type为Internal的,可以看到这里是unsafe分配的。
小结
通过nmt,我们可以快速的区别出问题到底是是不是来自jvm分配,不是话,就使用native的查找泄漏的方式查看,如果是的话,可以先通过summary查看到底是那个区域,然后利用detail.diff查看具体区域的分配。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/203540.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...