1.jvm内存模型
问题:
“你有没有处理过 JVM 相关的问题?”
“如何排查内存溢出 OOM?”
“堆内存溢出的常见原因和解决办法?”
“JVM 内存模型中,堆内存的作用是什么?”
答:之前项目启动时出现过 OOM,我通过添加 JVM 参数让它自动生成内存快照,分析后发现是初始化阶段加载了大量医嘱静态数据,导致堆内存不足。后来优化了初始化逻辑,只加载核心数据,启动就正常了。
细节补充:
堆内存是 JVM 中存储对象实例的区域
JVM 内存结构分线程私有和线程共享两部分。
线程私有包括程序计数器、虚拟机栈、本地方法栈,线程共享包括堆和方法区。
堆是最大的区域,存对象实例,分新生代和老年代,新生代有 Eden 区和 Survivor 区,短期对象先在 Eden 区,多次 GC 后存活的进老年代。
方法区存类信息、常量等,比如护理模块的类定义就在这里。虚拟机栈记录方法调用,调用方法时会创建栈帧入栈。
当时排查 OOM 时,可能用了 jmap 命令导出堆内存快照,然后用 MAT 工具分析,发现大量护理记录对象堆积在老年代,追溯到查询方法没有分页。也可能通过 JVM 参数 - XX:+HeapDumpOnOutOfMemoryError,让 OOM 时自动生成快照,再定位到具体代码行。
历史知识回顾:
OutofMemerryError是堆内存空间不足,但是最终抛出错误的地方,还是在栈里面
经典案例——
1、分页查询 没有加分页参数 一次性查询1000万条数据;(确实空间不足)
2、频繁操作string 没有 用 stringBuffer 或者 sringBuilder;(内存泄漏)
3、读写的stream 流、连接...开辟了资源没有释放,只管开辟,不管回收;
4.微服务启动,springcloud 很多组件,IOC很多bean实例;
StackOverflow是栈溢出 方法栈溢出,方法里面的引用、深度、太多了
经典案例——
1、无限递归;
设置大小
-Xmx=2G(设置最大内存) -Xmn500m(设置新生代内存,一般为3/8),
-xms=2G(设置初始内存,与最大内存一样,避免每次垃圾回收完成后重新分配JVM内存),-xss=128k(堆栈大小,jdk1.5之后为1M,这个值越大,创建线程越少)