当前位置: 首页 >> 基本常识
JVM 发生 OOM 的 8 种原因、及解决办法
  
  来源: www.fycek.com 点击:1757

小A:xx服务再次停止

B:第二天,我们走吧,去看看发生了什么

小A:OOM,我不知道要写哪个**代码,和*一样。

撸Java的同学会或多或少地遇到内存溢出(OOM)场景,但OOM的原因是多种多样的。

堆溢出

这种场景是最常见的,错误信息是:

原因

1,代码中可能有大对象分配

2.可能存在内存泄漏,这可能导致足够大的内存以在多个GC之后容纳当前对象。

溶液

1,检查是否有大对象分配,最有可能的是大数组分配

2,通过jmap命令,转储堆内存,使用mat工具进行分析,检查是否存在内存泄漏问题

3.如果没有发现任何明显的内存泄漏,请使用-Xmx来增加堆内存

4,另一点很容易被忽略,检查是否有大量的自定义Finalizable对象,或者它可能是在框架内提供的,考虑到它存在的必要性

永久代空间溢出

错误讯息:

原因

永久代是HotSot虚拟机方法区的具体实现,它存储由虚拟机加载的类信息,常量,静态变量,JIT编译代码等。

在JDK8之后,元空间取代了永久生成,元空间使用本地内存,其他细节也发生了变化:

字符串常量从永久代转移到堆

与永久生成相关的JVM参数已被删除

有几个可能的原因:

1,在Java7之前,使用String.intern()方法频繁出错

2.在运行期间生成大量代理类,导致方法区域爆炸且无法卸载

3,应用程序运行很长时间,没有重启

没有重启。 JVM进程通常在调试期间发生,如下面的tomcat官方网站常见问题解答:

溶液

因为OOM的原因比较简单,所以解决方案如下:

1.检查永久生成空间或元空间是否设置得太小

2,检查代码是否有大量的反射操作

3.转储后,检查mat以查看是否有大量由反射生成的代理类

4,放大,重启JVM

超出GC开销限制

此异常很少见,错误消息为:

原因

这是JDK6的新错误类型,通常由堆太小引起。 Sun正式定义了这一点:超过98%的时间花费在GC上,不到2%的堆内存被抛出。

溶液

1.检查项目中是否存在大量无限循环,或者使用大内存来优化代码。

2,添加参数-XX: -UseGCOverheadLimit禁用此检查,实际上这个参数无法解决内存问题,只是延迟了错误信息,最后是java.lang.OutOfMemoryError: Java堆空间。

3,转储内存,检查是否有内存泄漏,如果没有,增加内存。

方法堆栈溢出

错误讯息:

原因

这种异常主要是由创建的大量线程引起的。我遇到过一次,通过jstack获得了超过8000个线程。

溶液

1.每个线程堆栈大小的容量减少-Xss

2.线程总数也受系统可用内存和操作系统的限制。检查系统下是否存在此限制:

Procsyskernelpid_max

Procsyskernelthread-MAX

Maxuserprocess(ulimit -u)

Procsysvmmaxmapcount

非常规溢出

大多数学生可能不会遇到以下OOM异常,但您仍需要了解它

分配一个大数组

错误讯息:

这种情况通常是由不合理的数组分配请求引起的,并且JVM在为数组分配内存之前执行检查。要分配的数组是否可在平台上寻址,如果它不可寻址则会抛出此错误。

解决方案是检查代码中是否存在创建非常大的数组的位置。

交换溢出

错误消息:这种情况通常是由操作系统引起的。可能的原因是:

1,交换分区大小分配不足;

2.其他进程占用所有内存。

解决方案:

1.可以有选择地拆分其他服务流程

2,增加交换分区的大小,或增加机器内存的大小

本地方法溢出

错误讯息:

本地方法在运行时具有内存分配失败。与先前的方法堆栈溢出不同,方法堆栈溢出发生在JVM代码级别,而本地方法溢出发生在JNI代码或本地方法。

这种异常的可能性非常低,只能通过操作系统的本地工具进行诊断。这有点困难,或者放弃。

最后,分享一本采访书[Java核心知识点整理]涵盖JVM,锁定,高并发,反射,Spring原理,微服务,Zookeeper,数据库,数据结构等“,以及Java208面试问题(带答案) )!

加入我的粉丝群(Java Fill Road :)免费获取!掌握了这些知识点,你可以在面试中获得很多候选人,暴击9999分。机会是为那些准备好的人保留的,只有充分准备才能从候选人中脱颖而出。

——

友情链接:
沙湾信息网 版权所有© www.fycek.com 技术支持:沙湾信息网 | 网站地图