编写一份存在引发内存溢出(OOM)问题的项目,并以普通jar包的方式运行,来排除出项目哪里引发的问题。
项目本身很简单,Boot项目,对外提供一个接口,声明一个静态常量Map,不断的请求往Map存储大数据,使其快速沾满JVM空间,代码内容:
java
@Service
@Slf4j
public class JVMServiceImpl implements JVMService {
private static final Map<String, byte[]> MAP = new HashMap<>();
@Override
public void fun1() {
MAP.put(UUID.randomUUID().toString(), new byte[1024 * 1024 * 10]);
log.info("存储数据成功");
}
}
部署到linux服务器中,以后台启动的方式启动项目打好的jar包:
shell
nohup java \
-Djava.rmi.server.hostname=192.168.3.102 \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=1099 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Xms200m -Xmx200m \
-jar jvm-demo.jar > myDemo.log 2>&1 &
启动jdk自带的JVM监控工具:jconsole
浏览器访问多次接口,观察监控工具变化,以及接口返回情况:
正常情况:
JVM堆空间发生的情况:
继续访问:
堆空间已满
查看项目打印的日志:
已触发OOM错误
排查流程正式开启:
linux命令:jps查看java运行的项目
jdk命令:jmap生成堆转储快照
将*.hprof文件下载到本地,使用 JProfiler 分析工具打开
JProfiler官网下载地址:https://www.ej-technologies.com/download/jprofiler/files
可以看到类的实例数量:
点击最大对象:
发现了自己开发的包名下某个类下的某个对象特别大,自此发现了引发OOM的位置。
总结:使用jdk自带工具jmap
与工具JProfiler
来发现堆空间OOM错误。