撸Java的同学,多多少少都会碰到内存溢出(OOM)的场景,但是造成OOM原因却不止一个。
堆内存不足
这种场景最为常见,报错信息:
java.lang.OutOfMemoryError: Java heap space
原因
1、代码中可能存在大对象分配
2、可能存在内存泄露,导致在多次GC之后,还是无法找到一块足够大的内存容纳当前对象。
解决方法
1、检查是否存在大对象的分配,最有可能的是大数组分配
2、通过jmap命令,把堆内存dump下来,使用mat工具分析一下,检查是否存在内存泄露的问题
3、如果没有找到明显的内存泄露,使用 -Xmx 加大堆内存
4、还有一点容易被忽略,检查是否有大量的自定义的 Finalizable 对象,也有可能是框架内部提供的,考虑其存在的必要性
永久代/元空间溢出
报错信息:
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Metaspace
原因
永久代是 HotSot 虚拟机对方法区的具体实现,存放了被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等。
JDK8后,元空间替换了永久代,元空间使用的是本地内存,还有其它细节变化:
- 字符串常量由永久代转移到堆中
- 和永久代相关的JVM参数已移除
出现永久代或元空间的溢出的原因可能有如下几种:
1、在Java7之前