常见OOM异常

83 篇文章 7 订阅
7 篇文章 0 订阅

堆溢出

当报错信息java.lang.OutOfMemoryError后面带有java heap space时,说明是java堆溢出。
  • 1

由于Heap是用来存放实例的,堆溢出,也就说明了当前的实例对象过多,而且这些对象一直处于存活状态(JVM判断对象是否存活,是通过判断GC Roots和对象之间的是否存在可达路径)。出现这种问题,一般要考虑下列两种情况:

  • 内存泄露:

一般出现这种情形,需要判断是否是内存泄露,即一些无用对象一直被引用,导致GC无法有效回收它,这时可以通过一些工具,查看Heap dump,看看GC roots到对象之间的引用链,定位到泄露的对象。

  • 内存溢出:

另一种情形就是内存溢出,也就是这些对象的确是需要存活的,因此也就不存在GC回收异常。一般这种情况,可能是对象过大,或者对象的生命周期过长,需要从业务层面,减少这些对象在运行期的内存消耗。 
另外一种情形,也有可能是我们的堆分配的内存过小,可以通过配置堆的参数(-Xmx最大内存与-Xms 最小内存)来设置

栈溢出

栈溢出需要建立两个概念,一个就是整个java stack区域的大小,一个就是单个线程中stack的大小。

整个stack区的大小是由jvm的内存容量- heap容量 - 方法区容量 确定的,是一个固定的值。 
单个线程中 stack的大小也是固定的,可以通过 -Xss 配置

StackOverflowError,线程请求的栈的深度超过虚拟机允许的最大深度。

每个线程中stack的容量是固定,由于stack是用于存放各个方法的内部变量表的,所以,当大量的方法被调用,而又未及时结束,或者单个方法内部定义了大量局部变量,使单个栈帧很大,这样使得占用的空间超过了单个线程中stack的深度,因此会报这个异常。

OutOfMemoryError 虚拟机扩展栈时无法分配足够的内存空间

一般情况下,当启用一个线程时,就会给这个线程分配一个固定大小的stack,由于整个java stack区的大小是有限的,当我们的线程过多时,就会抛出OutOfMemoryError异常。由此可见,单个线程stack的大小并非越大越好,因为这与我们的线程数息息相关。

方法区溢出 
方法区是用于存放类的定义Class文件和常量池等,由此可见,当类或者常量池过多时,会造成方法区溢出

当报错信息java.lang.OutOfMemoryError后面带有PremGen space时,说明是方法区溢出。
  • 1

当前的一些框架,如Spring、Hibernate等,会使用CGlib技术对类进行增强,相应地会增加类的大小; 
还有一些应用,会动态生成JSP文件,JSP文件是需要编译成Class文件的,大量的文件也有溢出的可能; 
或者开发代码中往常量池添加过多的常量,也有可能造成常量池溢出。 
另外一种可能就是我们的应用本身的类就太多,而方法区设置的容量不足,也会容易溢出。 
设置方法区的大小,可通过配置-XX:PremSize 设置最小值,-XX:MaxPremSize设置最大值。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值