Java程序是基于GC的,在启动初始,就申请了足量的内存池,再加上JIT等编译器的实时优化,速度并不比直接用C++语言写的慢。Java语言同时由于反射和可观测等特点,再加上JFR这种神器,在发生问题的时候比二进制文件更容易找到它的根源。
最近在看RCA(Root Cause Analysis)的东西,不小心发现了yCrash这么个东西。它的几段问题小代码写的非常典型,我们可以稍微看一下,来看看Java应用程序常见的几个崩溃场景。
1.堆空间溢出
OOM 一般是内存泄漏引起的,表现在 GC 日志里,一般情况下就是 GC 的时间变长了,而且每次回收的效果都非常一般。GC 后,堆内存的实际占用呈上升趋势。
下面的代码是死循环,持续向HashMap里塞数据,由于myMap属于GCRoots,始终得不到释放,所以它最终的结果就是OOM。
import java.util.HashMap;
public class OOMDemo {
static HashMap<Object, Object> myMap = new HashMap<>();
public static void start() throws Exception {
while (true) {
myMap.put("key" + counter, "Large stringgggggggggggggggggggggggggggg"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "ggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+ "ggggggggggggggggggggggggggggggggggggggggggggg