Java内存泄漏OMM

JVM 发生 OOM 的 8 种原因、及解决办法

高手总结的9种 OOM 常见原因及解决方案

堆溢出

这种场景最为常见,报错信息:

java.lang.OutOfMemoryError: Java heap space

原因

1.代码中可能存在大对象分配(如大数组)

2.可能存在内存泄漏,多次GC后,仍然无法找到一块足够大的内存容纳当前对象

解决方法

1.对于大对象分配,条件允许的话,可以扩大堆内存的分配空间,是否可以对大对象进行分割

2.对于内存泄漏,可以使用(jmap和jconsole监测),检查代码,通过 jmap 命令 dump 内存对象

内存泄漏:指对象没有被引用也没有被回收

永久代/元空间溢出

image-20200801230414484

原因

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

2、类class信息太多

解决方法

1.增加永久代空间

2、重启JVM

3、jmap dump内存对象检查

jmap-dump:format=b,file=dump.hprof

4.看看程序是否存在大量反射操作

方法区,永久代,元空间的一些知识

JVM之 方法区、永久代(PermGen space)、元空间(Metaspace)三者的区别

方法区主要存储类的相关信息,常量静态变量等

JDK6、JDK7 时,方法区 就是 PermGen(永久代)。
JDK8 时,方法区就是 Metaspace(元空间)

Metaspace(元空间)和 PermGen(永久代)类似,都是对 JVM规范中方法区的一种落地实现。(hotspot)不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存

image-20200801224346252

为什么要删除永久代

永久代的大小很难确定,太小容易内存溢出,触发full gc,太大则容易导致老年代溢出。

元空间保存在本地内存中,元空间的最大可分配空间就是系统可用内存空间,可以避免永久代的内存溢出问题

字符串常量池存在永久代中,容易发生内存溢出和性能问题

GC执行频繁

GC overhead limit exceeded,程序大部分时间都用于GC,且回收的内存极少。当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 java.lang.OutOfMemoryError:GC overhead limit exceeded 错误。简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收。

跟堆溢出类似

虚拟机栈溢出

StackOverflow 栈深度过深,检查程序递归代码

Unable to create new native thread

不能创建线程,一般是由于程序线程过多

解决方案

1.检查是否创建线程过多,规范使用线程,如使用线程池创建

2.升级机器配置(如果确实需要这么多线程,机器无法满足)

3.调整操作系统的线程数阈值操作

系统会限制进程允许创建的线程数,使用ulimit -u命令查看限制。

4、通过 -Xss 降低的每个线程栈大小的容量

设置单个线程占用的内存大小

5、减少堆内存大小(如果堆内存分配过大,堆内存少了,虚拟机栈内存就自然大了)

swap space溢出

java.lang.OutOfMemoryError: Out of swap space

该错误表示所有可用的虚拟内存已被耗尽(向操作系统申请内存时耗尽)。虚拟内存(Virtual Memory)由物理内存(Physical Memory)和交换空间(Swap Space)两部分组成。当运行时程序请求的虚拟内存溢出时就会报 Outof swap space? 错误。

这种情况一般是**操作系统导致的,**可能的原因有:

1.物理内存不足或交换机内存不足,增加交换区大小,检查本地程序内存占用情况

2.升级配置升级机器内存

分配超大数组

报错信息 :

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

这种情况一般是由于不合理的数组分配请求导致的,在为数组分配内存之前,JVM 会执行一项检查。要分配的数组在该平台是否可以寻址(addressable),如果不能寻址(addressable)就会抛出这个错误。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部