这篇文章将为大家详细讲解有关JAVA中怎么排查内存泄漏,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
内存泄漏
内存泄漏(Memory Leak)是指程序中一个对象或变量无法回收,一直保存在内存中。这样的对象或变量一直累计,最终导致内存溢出(Out Of Memory)。
内存泄漏原因
内存泄漏大概有以下几个原因
1.静态集合存放对象
长周期对象持有了短周期的对象的引用,就可能导致内存泄漏。如果集合是静态的,那么该集合的生命周期就和程序的生命周期一致。且对象存放在静态集合中,所以在整个程序的生命周期内,对象都无法被释放,最终导致内存泄漏。
2.连接未关闭
数据库连接,网络连接,IO连接等生成连接后,如果没有调用close方法,则会造成相关的对象无法被回收,导致内存泄漏。
3.单例对象
单例对象的生命周期和程序的生命周期也是一致的,所以如果单例对象引用了一个外部对象,那么这个外部对象在程序结束前也是无法被释放的。存在内存泄漏的风险。
4.改变对象HASH值
如果一个对象被存入HashSet集合,再修改对象参与Hash值计算的属性,那么对象的Hash值就会改变。由于对象存入HashSet集合时存放的位置是根据旧Hash值获得的,那么当Hash变动后,已经找不回原来的位置,这就导致这个对象无法在HashSet被搜索到,也无法被删除。由于一直存在于HashSet,那么除非HashSet被释放,否则该对象将一直被HashSet引用,从而无法被释放,造成内存泄漏。
5.内部类持有外部类引用
如果一个内部类调用了一个外部类的方法,并且将内部类作为参数传递过去。那么如果外部类不释放这个内部类,这个内部类就无法释放,就可能造成内存泄漏。
排查步骤
1.通过jps命令找出正在执行的虚拟机进程,获取进程的在虚拟机中的唯一ID,命令格式如下:
Jps [options] [hostid]
例如 jps -l,结果如下:
options的参数如下:
-q | 不输出类名、Jar名和传入main方法的参数 |
-m | 输出传入main方法的参数 |
-l | 输出main类或Jar的权限名 |
-v | 输出传入JVM的参数 |
hostid可以用来查看其他服务器上虚拟器的进程,默认是本机
2.获取唯一ID,可以使用jstat监视进程状态,命令格式如下:
Jstat [option vmid [interval[s|ms] [count]]]
例如 jstat -gc 12116 1000 4
每隔1000毫秒查询某个进程的已使用空间占总空间百分比,总共查4次,结果如下
S0C | 生存区0容量 |
S1C | 生存区1容量 |
S0U | 生存区0使用量 |
S1U | 生存区1使用量 |
EC | Eden区容量 |
EU | Eden区使用量 |
OC | 老年代容量 |
OU | 老年代使用量 |
MC | 方法区容量 |
MU | 方法区使用量 |
CCSC | 压缩类空间容量 |
CCSU | 压缩类空间使用量 |
YGC | 年轻代GC次数 |
YGCT | 年轻代GC耗时 |
FGC | FULL GC 次数 |
FGCT | FULL GC 耗时 |
GCT | GC总耗时 |
option的参数如下
-class | 显示加载class的数量,及所占空间等信息 |
-compiler | 显示VM实时编译的数量等信息 |
-gc | 可以显示gc的信息,查看gc的次数,及时间 |
-gccapacity | 可以显示VM内存中三代(young,old,perm)对象的使用和占用大小 |
-gcutil | 统计gc信息 |
-gcnew | 年轻代对象的信息 |
-gcnewcapacity | 年轻代对象的信息及占用量 |
-gcold | old代对象的信息 |
-gcoldcapacity | old代对象的信息及占用量 |
-gcpermcapacity | perm对象的信息及占用量 |
-printcompilation | 当前VM执行的信息 |
3.可以使用jmap分析堆内存使用情况,命令格式如下:
jmap [option] pid
例如:jmap -histo:live 6088,结果如下
没有参数打印进程的类加载器和类加载器加载的持久代对象
option的参数如下
-heap | 查看进程堆内存使用情况,包括使用的GC算法、堆参数配置和各代中堆内存的使用情况 |
-histo | 查看堆内存中的对象数目、大小统计 |
-histo:live | 查看堆内存中活的对象数目、大小统计,并进行一次GC |
-dump:format=b,file=dumpFileName | 用jmap把进程内存使用情况dump到文件中 |
通过检查类的占用情况可以分析是哪个类出现了内存泄漏,实在不行,也可以通过dump命令生成dump文件进一步分析。
例如
jmap -dump:format=b,file=20210512.dump 6088
然后使用jvisualvm工具分析dump文件
关于JAVA中怎么排查内存泄漏就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。