VM 发生 OOM 的 8 种原因、及解决办法
1. 堆空间使用过多
原因:
1、Java 堆中无法再分配对象
2、对象被引用,导致对象无法被 GC 回收
3、应用程序过度使用 finalizer。finalizer 对象不能被 GC 立刻回收。
解决方案
1、通过调节JVM参数 -Xmx 增加堆大小
2、优化程序,解决内存泄漏问题
注:
finalize 方法高度依赖 JVM 和 GC,当一个对象被标记后,便会被 JVM 包装成 Finalizer 对象,然后,被 JVM 设置到 Reference 的静态属性 pending 中,Reference 的内部线程则会将这个 pending 放入到构造函数的队列中。
Finalizer 的内部线程则会从队列中取出 Finalizer 对象,并调用其包装的实际对象的 finalize 方法。
所以,finalize 方法需要两个线程来处理他,一个是 ReferenceHandler ,一个是 FinalizerThread。
前者负责将 Finalizer 对象放入到 Reference 队列中,后者负责从队列中取出 Finalizer 对象并调用实际对象的 finalize 方法。
同时,GC 大概也要做 2 件事情,一个是创建 Finalizer 对象,一个是将该对象设置到自己的 pending 属性中。
pending 英[ˈpendɪŋ]:待定
2. GC 开销过大
原因
1、Java不断的
解决方案
1、通过调节JVM参数 -Xmx 增加堆大小
2、通过调节JVM参数 -XX:-UseGCOverheadLimit 取消 GC 开销限制
3、修复应用程序中的内存泄漏
3. 请求的数组大小超过虚拟机限制
原因
1、应用程序试图分配一个超过堆大小的数组
解决方案
1、通过调节JVM参数 -Xmx 增加堆大小
2、优化代码,不要一次性分配这么大的数组
4. Perm gen 空间
gen:情报
原因
Perm gen 空间包含:
1、类的名字、字段、方法
2、与类相关的对象数组和类型数组
3、JIT 编译器优化
当 Perm gen 空间用尽时,将抛出异常。
PermGen原理:
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。 如果你的WEB APP下都用了大量的第三方jar, 其大小 超过了jvm默认的大小(4M)那么就会产生此错误信息了。
解决方案
1、通过调节JVM参数 -XX: MaxPermSize 增加 Permgen 大小
5. Metaspace
原因
1、从 Java 8 开始 Perm gen 改成了 Metaspace,在本机内存中分配 class 元数据(称为 metaspace)。如果 metaspace 耗尽,则抛出异常
解决方案
1、调节参数 -XX: MaxMetaSpaceSize 增加 metaspace 大小
2、增加服务器的内存
3、检查代码,可能是bug引起的
6. 发生 stack_trace_with_native_method
原因
1、native method 分配失败
2、查看堆栈信息,最顶层的帧是 native method
解决方案
1、使用操作系统本地工具进行诊断
7. 杀死进程或子进程
原因
1、内存不足,在可用内存极低的情况下会杀死进程
解决方案
1、将进程迁移到不同的机器上
2、给机器增加更多内存
3、这是由操作系统而非 JVM 触发的。
浙公网安备 33010602011771号