Java出现OutOf MemoryError(OOM 错误)的原因有哪些?出现OOM错误后,怎么解决?

内存溢出和内存泄漏的区别

一、内存溢出(Memory Overflow)指的是程序在申请内存时,没有足够的可用内存供其使用,导致程序无法正常执行或崩溃。这通常发生在以下情况下:
1、程序申请了过多的内存,超过了系统可用的内存资源。
2、程序没有正确释放已经申请的内存,导致内存被占用而无法再次使用。

二、内存泄漏(Memory Leak)指的是程序在运行过程中,申请了一块内存但没有释放,导致这块内存无法再被程序使用。内存泄漏通常发生在以下情况下:
1、程序中存在未释放的动态分配的内存,即程序没有调用对应的释放内存的函数(如delete或free)。
2、程序中存在指针引用错误,导致无法访问到需要释放的内存。

三、区别:
1、触发条件不同:内存溢出是因为申请的内存超过了系统可用的内存资源,而内存泄漏是因为未释放已经申请的内存。
2、影响范围不同:内存溢出可能导致程序崩溃或异常终止,影响整个程序的执行;而内存泄漏会逐渐消耗系统的可用内存,导致系统性能下降。
3、解决方法不同:对于内存溢出,可以通过增加可用内存或优化内存使用来解决;对于内存泄漏,需要找到未释放的内存并进行释放。

Java出现OutOf MemoryError(OOM 错误)的原因有哪些?出现OOM错误后,怎么解决?

一、错误原因:此OOM是由于JVM中heap的最大值不满足需要。
java.lang.OutOfMemoryError: Java heap space

解决方法:调高堆内存(heap)的最大值,即-Xmx的值调大。2) 如果你的程序存在内存泄漏,一味的增加heap空间也只是推迟该错误出现的时间而已,所以要检查程序是否存在内存泄漏。

  • -Xms用于为JVM启动时申请的初始Heap值,默认为操作系统物理内存的1/64但小于1G。默认当空余堆内存大于70%时,JVM会减小heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRation来指定这个比列。
  • -Xmx 为JVM运行时可申请的最大Heap值,默认值为物理内存的1/4但小于1G,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRation来指定这个比列。
  • Server端JVM最好将-Xms和-Xmx设为相同值,避免每次垃圾回收完成后JVM重新分配内存;开发测试机JVM可以保留默认值。(例如:-Xms4g)。
    详情参考链接:JVM常用内存参数配置
二、错误原因:此OOM是由于JVM在GC时,对象过多,导致内存溢出,建议调整GC的策略,在一定比例下开始GC而不要使用默认的策略,或者将新代和老代设置合适的大小,需要进行微调存活率。
java.lang.OutOfMemoryError: GC overhead limit exceeded

解决方法:改变GC策略,在老代80%时就是开始GC,并且将-XX:SurvivorRatio(-XX:SurvivorRatio=8)和-XX:NewRatio(-XX:NewRatio=4)设置的更合理。

三、错误原因:此OOM是由于JVM中perm的最大值不满足需要。
java.lang.OutOfMemoryError: Java perm space

解决方法:调高heap的最大值,即-XX:MaxPermSize的值调大。

perm一般是在JVM启动时加载类进来,如果是JVM运行较长一段时间而不是刚启动后溢出的话,很有可能是由于运行时有类被动态加载进来,此时建议用CMS策略中的类卸载配置。如:-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled。

四、错误原因:当JVM向OS请求创建一个新线程时,而OS却由于内存不足无法创建新的native线程。
java.lang.OutOfMemoryError: unable to create new native thread

解决方法:如果JVM内存调的过大或者可利用率小于20%,可以建议将heap及perm的最大值下调,并将线程栈调小,即-Xss调小,如:-Xss128k。

  • 操作系统(Operating System,简称OS)是计算机系统中的核心软件,它是管理和控制计算机硬件与软件资源的系统软件。操作系统提供了一个运行环境,使得用户可以方便地与计算机进行交互,并且能够有效地管理计算机的资源,如处理器、内存、磁盘、网络等。
  • 操作系统的主要功能包括:
    进程管理:负责创建、调度和终止进程,以及管理进程间的通信和同步。
    内存管理:负责分配和回收内存资源,以及进行内存的保护和共享。
    文件系统:负责管理文件和目录,提供对文件的读写和访问控制。
    设备管理:负责管理计算机的各种设备,如硬盘、打印机、键盘等。
    用户界面:提供给用户与计算机交互的方式,如命令行界面和图形界面。
    操作系统的种类有很多,常见的有Windows、Linux、macOS等
五、错误原因:此类信息表明应用程序(或者被应用程序调用的APIs)试图分配一个大于堆大小的数组。例如,如果应用程序new一个数组对象,大小为512M,但是最大堆大小为256M,因此OutOfMemoryError会抛出,因为数组的大小超过虚拟机的限制。
java.lang.OutOfMemoryError: Requested array size exceeds VM limit

解决方法:1) 首先检查heap的-Xmx是不是设置的过小。2) 如果heap的-Xmx已经足够大,那么请检查应用程序是不是存在bug,例如:应用程序可能在计算数组的大小时,存在算法错误,导致数组的size很大,从而导致巨大的数组被分配。

  • API(Application Programming Interface)是一组定义了软件件之间交互的规则和协议。它允许不同的软件系统之间进行通信和数据交换,使得开发者可以利用已有的功能来构建自己的应用程序。
  • APIs可以分为不同的类型,包括:
    1.Web APIs:用于通过网络进行通信的API,常见的有RESTful API和SOAP API。Web APIs通常使用HTTP协议进行通信,可以通过发送HTTP请求来获取数据或执行操作。
    2.库APIs:也称为函数库或类库,提供了一组函数或类,开发者可以直接调用这些函数或类来实现特定的功能。库APIs通常以静态链接库(.lib)或动态链接库(.dll)的形式提供。
    3.操作系统APIs:用于与操作系统进行交互的API,例如Windows API和Linux API。操作系统APIs提供了访问底层系统资源和功能的接口,开发者可以使用这些接口来创建应用程序。
    4.第三方APIs:由第三方提供的API,用于访问其提供的服务或功能。例如,社交媒体平台提供的API可以让开发者获取用户信息或发布内容。
  • 使用APIs可以带来很多好处,包括:
    提高开发效率:通过使用已有的APIs,开发者可以节省大量的时间和精力,无需从头开始编写所有的功能。
    提供标准化接口:APIs定义了标准的接口规范,使得不同的软件系统可以进行无缝集成和交互。
    促进合作与创新:APIs可以让不同的开发者或组织共享和交换功能,促进合作和创新。
六、错误原因:抛出这类错误,是由于从native堆中分配内存失败,并且堆内存可能接近耗尽。这类错误可能跟应用程序没有关系,例如下面两种原因也会导致错误的发生:1) 操作系统配置了较小的交换区。2)系统的另外一个进程正在消耗所有的内存。
java.lang.OutOfMemoryError: request < size> bytes for < reason>. Out of swap space

解决办法:1) 检查os的swap(交换分区)是不是没有设置或者设置的过小。2) 检查是否有其他进程在消耗大量的内存,从而导致当前的JVM内存不够分配。

  • 在Linux下,SWAP的作用类似Windows系统下的“虚拟内存”。当物理内存不足时,拿出部分硬盘空间当SWAP分区(虚拟成内存)使用,从而解决内存容量不足的情况。
  • SWAP意思是交换,顾名思义,当某进程向OS请求内存发现不足时,OS会把内存中暂时不用的数据交换出去,放在SWAP分区中,这个过程称为SWAP OUT。当某进程又需要这些数据且OS发现还有空闲物理内存时,又会把SWAP分区中的数据交换回物理内存中,这个过程称为SWAP IN。
  • swap大小是有上限的,一旦swap使用完,操作系统会触发OOM-Killer机制,把消耗内存最多的进程kill掉以释放内存。

注意:虽然有时< reason>部分显示导致OOM的原因,但大多数情况下,< reason>显示的是提示分配失败的源模块的名称,所以有必要查看日志文件,如crash时的hs文件。

  • 29
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Java 程序可能出现 OOM(Out of Memory)的情况有以下几种: 1. 堆内存不足:Java 程序的堆内存用于存储对象实例,如果堆内存不足,就会出现 OOM 问题。例如,Java 程序中创建了大量的对象实例,但是堆内存不足以存储这些对象实例,就会出现 OOM 问题。 2. 元空间不足:Java 8 引入了元空间(Metaspace)来代替 PermGen,用于存储类元数据。如果元空间不足,就会出现 OOM 问题。例如,Java 程序中动态生成了大量的类,但是元空间不足以存储这些类的元数据,就会出现 OOM 问题。 3. 栈空间不足:Java 程序的栈空间用于存储方法调用的状态和局部变量等信息。如果栈空间不足,就会出现 StackOverflowError(栈溢出)问题。例如,Java 程序中递归调用了一个方法,但是栈空间不足以存储递归调用的状态,就会出现 StackOverflowError 问题。 4. 本地内存不足:Java 程序可以使用本地方法库来调用本地系统资源,例如调用 C 语言编写的库文件。如果本地内存不足,就会出现 OOM 问题。例如,Java 程序中调用了大量的本地方法,但是本地内存不足以存储这些方法的数据和状态,就会出现 OOM 问题。 5. 永久代(PermGen)不足:Java 7 及之前的版本使用 PermGen 来存储类元数据和字符串常量等信息。如果 PermGen 不足,就会出现 OOM 问题。例如,Java 程序中动态生成了大量的类或者字符串常量,但是 PermGen 不足以存储这些信息,就会出现 OOM 问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值