Java 常见的几种内存溢出异常的原因及解决

内存溢出的异常有很多,并且每种内存溢出都会有不同的异常信息和解决方式,下面会列出常见的几种内存溢出异常

堆内存溢出

java.lang.OutOfMemoryError: Java heap space

原因:

  • 当堆内存不足,并且已经达到JVM设置的最大值,无法继续申请新的内存,存活的对象在堆内存中无法被回收,那么就会抛出该异常,表示堆内存溢出。
  • 当一次从数据库查询大量数据,堆内存没有足够的内存可以存放大量的数据
  • 大量的强引用对象在堆内存中存活,GC无法回收这些对象,新创建的对象在新生代无法进行分配,Full GC仍然无法进行回收

解决方案:

  • 查看当前JVM的堆内存配置是否太小,可以考虑增加堆内存大小

JAVA_OPTS="-server -Xms1024m -Xmx1024m"

表示将堆内存的初始值和最大值都设置为1024m

-Xms设置堆内存的初始值

-Xmx设置堆内存的最大值

-Xms和-Xmx最好设置相同的内存大小,可以防止因为JVM频繁进行内存的调整影响稳定性和使用

  • 查看代码中是否有从数据库中一次加载大量数据的情况,或者代码中有大量强引用无法进行回收

通过JVM参数:-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出的时候Dump出当前的堆内存快照,便于保留快照分析

栈内存溢出

java.lang.outOfMemoryError:StackOverFlow Error

原因:

  • 线程请求的栈深度大于虚拟机允许的最大深度,抛出StackOverflowError
  • 虚拟机在扩展栈时无法申请到足够的内存空间,抛出OutOfMemoryError

解决方案:

  • 检查代码是否出现深度递归的情况,或者递归的终止条件没有设置
  • 如果是线程的栈内存空间过小,则通过-Xss设置每个线程的栈内存空间

默认的-Xss参数的大小应该是1M

栈内存是线程私有的,如果需要创建更多的线程,那么就需要将每个线程的栈内存空间减小,通过-Xss参数设置每个线程的栈内存空间

配置参数: JAVA_OPTS="-server -Xms1024m -Xmx1024m -Xss128k"

jdk8如果没有配置-Xss默认大小为512k

-Xss 设置每个线程的堆栈大小,一般默认512~1024kb,和jdk版本有关

方法区和运行时常量池内存溢出

java.lang.outOfMemoryError: PermGen space

原因:

  • 方法区存放的是Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等,内存溢出的原因可能是加载的类过多导致方法区没有足够的内存
  • 如果程序中大量使用cglib或者动态代理等对目标类进行代理,那么在运行时会生成大量的代理类,如Spring、Hibernate等框架。所以生成的代理类过多导致方法区没有足够的内存

解决方案:

  • 减少没有必要的Class加载,防止方法区内存溢出并且减少程序的编译时间
  • 通过JVM参数设置方法区的大小,-XX:PermSize和-XX:MaxPermSize设置方法区的大小

运行时常量池是方法区的一部分,所以增加方法区的内存大小,相当于间接的增加了运行时常量池的内存大小

本机直接内存溢出

Direct buffer memory

Java 允许应用程序通过 DirectByteBuffer 直接访问堆外内存,许多高性能程序通过 DirectByteBuffer 结合内存映射文件(Memory Mapped File)实现高速 IO

原因:

DirectByteBuffer 的默认大小为 64 MB,一旦使用超出限制,就会抛出 Direct buffer memory 错误。使用NIO则可能会出现该异常

解决方案:

DirectMemory的内存大小可以通过-XX:MaxDirectMemorySize指定,如果没有设置,则默认和Java堆最大值(-Xmx)一样

元空间内存溢出

Metaspace

Jdk8 之后使用元空间(metaspace)代替永久代,元空间和永久代最大的区别是元空间的内存使用的是本地内存,而永久代使用的是JVM的内存

永久代、元空间都是方法区的实现,方法区是规范

原因:

元空间中存储的是类信息、常量池、方法描述等信息,直接使用本地内存,当本地内存不足的时候,会抛出OutOfMemoryError:Metaspace异常

解决方案:

虽然元空间的内存不是由JVM控制,不过可以通过JVM参数来设置分配的内存空间的大小-XX:MaxMetaspaceSize配置参数

以上就是Java 常见的几种内存溢出异常及解决的详细内容,更多关于Java 内存溢出的资料请关注我们其它相关文章!

(0)

相关推荐

  • java内存泄漏与内存溢出关系解析

    这篇文章主要介绍了java内存泄漏与内存溢出关系解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory: 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光. memory leak会最终会导致out of memory!

  • Java虚拟机内存溢出与内存泄漏

    一.基本概念 内存溢出:简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出. 内存泄漏:内存泄漏指程序运行过程中分配内存给临时变量,用完之后却没有被GC回收,始终占用着内存,既不能被使用也不能分配给其他程序,于是就发生了内存泄漏. 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory: 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间

  • Java 内存溢出的原因和解决方法

    你是否遇到过Java应用程序卡顿或突然崩溃的情况?您可能遇到过Java内存泄漏.在本文中,我们将深入研究Java内存泄漏的确切原因,并推荐一些最好的工具来防止内存泄漏发生. 什么是JAVA内存泄漏? 简单地说,Java内存泄漏是指对象不再被应用程序使用,而是在工作内存中处于活动状态. 在Java和大多数其他编程语言中,垃圾收集器的任务是删除不再被应用程序引用的对象.如果不选中,这些对象将继续消耗系统内存,并最终导致崩溃.有时java内存泄漏崩溃不会输出错误,但通常错误会以java.lang.Ou

  • JAVA内存溢出解决方案图解

    这篇文章主要介绍了JAVA内存溢出解决方案图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.在apache-tomcat-7.0.70\bin\catalina.bat(Linux 系统则在catalina.sh) 文件下的 echo Using CATALINA_BASE: "%CATALINA_BASE%" 上面插入以下代码 set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=256

  • Java内存溢出案例模拟和原理分析过程

    在JVM虚拟机规范中,Java虚拟机运行时数据区域除了程序计数器(Program Counter Register)外都有可能出现OutOfMemoryError的情况,使用Hotspot虚拟机简单的模拟堆栈内存溢出的场景,方便快速定位是什么区域的内存溢出. 堆 通过VM参数设置Java堆的大小,避免堆可扩展内存(设定-Xms和Xmx一样可避免堆自动扩展): 通过设定-XX:+HeapDumpOnOutOf-MemoryError可以让虚拟机在出现内存溢出异常的时候Dump出当前的内存堆转储快照

  • Java内存溢出实现原因及解决方案

    1.JVM Heap(堆)溢出:java.lang.OutOfMemoryError: Java heap space JVM在启动的时候会自动设置JVM Heap的值, 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置.Heap的大小是Young Generation 和Tenured Generaion 之和.在JVM中如果98%的时间是用于GC,且可用的Heap size 不足2%的时候将抛出此异常信息. 解决方法:手动设置JVM Heap(堆)的大小. Java堆用于储存

  • 简单了解JAVA内存泄漏和溢出区别及联系

    1.内存泄漏memory leak : 是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出. 2.内存溢出 out of memory : 指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出. 3.二者的关系: 内存泄漏的堆积最终会导致内存溢出 内存溢出就是你要的内存空间超过了系统实际分配给你的空间

  • 详解Java内存溢出的几种情况

    JVM(Java虚拟机)是一个抽象的计算模型.就如同一台真实的机器,它有自己的指令集和执行引擎,可以在运行时操控内存区域.目的是为构建在其上运行的应用程序提供一个运行环境.JVM可以解读指令代码并与底层进行交互:包括操作系统平台和执行指令并管理资源的硬件体系结构. 1. 前言 JVM提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,大部分情况下不会出现内存泄漏和内存溢出问题.但是基本不会出现并不等于不会出现,所以掌握Java内存模型原理和学会分析出现的内存溢出或内存泄漏,对于使用J

  • Java虚拟机常见内存溢出错误汇总

    一.引言 从事java开发的小伙伴在平时的开发工作中,应该会遇见各式各样的异常和错误,在实际工作中积累的异常或者错误越多,趟过的坑越多,就会使我们编码更加的健壮,就会本能地避开很多严重的坑.以下介绍几个Java虚拟机常见内存溢出错误.以此警示,避免生产血案. 二.模拟Java虚拟机常见内存溢出错误 1.内存溢出之栈溢出错误 package com.jayway.oom; /** * 栈溢出错误 * 虚拟机参数:-Xms10m -Xmx10m * 抛出异常:Exception in thread

  • JAVA 内存溢出案例汇总

    写在前面 作为程序员,多多少少都会遇到一些内存溢出的场景,如果你还没遇到,说明你工作的年限可能比较短,或者你根本就是个假程序员!哈哈,开个玩笑.今天,我们就以Java代码的方式来列举几个典型的内存溢出案例,希望大家在日常工作中,尽量避免写这些low水平的代码. 定义主类结构 首先,我们创建一个名称为BlowUpJVM的类,之后所有的案例实验都是基于这个类进行.如下所示. public class BlowUpJVM { } 栈深度溢出 public static void testStackOv

随机推荐