JAVA中内存爆炸浅析
JVM内存
1、-xms:
- 内存占用预热过程
jvm所占有的操作系统内存最小设置参数。并不是JVM启动时直接划分内存到值的设置,内存达到最小值是有预热过程,除非程序使用内存太大,等于或者超过设置最小内存,否则是JVM逐步加载至此值。
- 语义
当JVM发生GC时,保留JVM使用最小内存的值。 - JVM直接申请至最小内存设置
通过设置:-xx:+AlwaysPretouch,JVM启动时直接申请内存至设置的-xms;但是如果程序在运行过程中,从未达到-xms的设置,那么JVM占用内存依然小于-xms设置。 建议在意识到程序一定会占用大内存空间时,考虑设置AlwaysPreTouch值。比如:多线程并发场景。
2、OOM
- 当JVM来不及GC时,会发生OOM
以下程序不会发生oom,执行结果为FullGC。因为在程序中内存不断进行GC,保证内存回收,释放,分配。
程序中设置JVM最大内存:512M,循环中每次分配256M空间,程序每次循环时发现内存不够,而且tmp是局部变量,直接进行GC操作。一直分配内存,做GC操作。
如代码进行如下修改,则可能会出现oom情况
实例化的byte对象被List:space一直占用,JVM无法进行GC操作。当内存不够用时,会发生oom。
如何定位oom问题呢?
首先一般发生oom问题后,JVM进程会停止运行,此时无法用工具进行现场分析。我们可以通过内存快照方式进行排查,定位。
a、设置出现oomError时,保存内存快照的文件位置
b、下载内存快照:jmap -dump:format=b,file=elipse.hprof 2622 其中2622为linux下eclipse进程编号
使用jvisualvm (C:\Program Files (x86)\Java\jdk1.8.0_45\bin)进行分析。
3、隐式System.gc()排查
在程序运行过程中,虽然代码未显式使用系统gc()方法,但是有可能依赖的第三方包中存在gc(),方法调用。如果依赖多个第三方包,如何排查依赖包隐式进行gc()呢?我们可以使用BTrace工具进行排查。
隐式gc的现象是:GC日志中出现大量:【GC (System.gc())】
注意点:使用BTrace进行gc排查前提是,必须定位到是哪个类可能存在调用第三方包,产生主动GC操作。
排查出第三方依赖包产生GC操作后,如何处理:
a、设置:-xx:DisableExplicitGC 此方式比较粗暴,可能会误伤哦
b、自己逐步排查,放过或者解决掉
BTrace使用
1、