探索OutOfMemoryError与StackOverflowError

    本文的目的有两个:1.OutOfMemoryError与StackOverflowError异常在哪个区域发生,2.解决问题的思路;因工作中发现团队的好多人知道一堆定位工具,但对于定位思路模糊不清,不知道所报异常具体问题在哪里胡乱分析,效率低下,故而总结下文。

    一、OutOfMemoryError异常

    1.1 Java堆(-Xmx -Xms)

     1.1.1标识: java.lang.OutOfMemoryError:heap space(比较常见)

     1.1.2产生的原因:1.内存泄漏(Memory Leak)

                                     2.内存溢出(Memory OverFlow)

     1.1.3定位手段:可以通过参数-XX:+HeapDumpOnOutOfMemoryError让虚拟机在出现内存异常的时候Dump出当前内存堆转存快照以便进行事后分析。

     内存泄漏:查看泄漏对象到GC Roots的引用链,找到泄漏对象是通过什么引用路径、与那些GC Roots想关联,才导致垃圾回收器无法回收他们。

    内存溢出:对象是必须存在的,得检查Java虚拟机的堆参数(-Xmx -Xms)设置,与机器的内存对比,看看是否还有向上调整的空间。再从代码上检查是否存在某些生命周期过长的对象,持有状态时间过长,存储设计不合理等情况,尽量减小程序运行的情况。

     1.2虚拟机栈与本地方法栈

      当虚拟机栈允许动态扩展,当扩展栈的容量无法申请到足够内存时,将抛出OutOfMemoryError,但HotSpot虚拟机选择是不支持扩展,所以除非在创建线程申请内存时因无法获取到足够内存时出现OutOfMemoryError异常,否在在线程运行时不会因扩展而导致内存溢出的。

     1.3方法区域运行时常量池溢出(-XX:PermSize -XX:MaxPermSize )

     1.3.1标识: java.lang.OutOfMemoryError: PermGen space (经常出现)

     1.3.2产生的原因:

      1 JDK1.6产生大量运行时常量会导致常量池空间不足会产生PermGen space,JDK1.7之后将运行时常量移至Java堆中所以出现的溢出会是heap space

       2.运行时生成大量的动态类,如使用到CGLib,大量的Jsp或是动态生成JSP的应用,如:基于OSGI的应用,方法区会因空间不足产生 PermGen space,到JDK1.8之后方法区用元空间替代,所以不会产生 PermGen space不足异常

      备注:元空间必要参数:(-XX:MetaspaceSiz -XX:MaxMetaspaceSize)

       使用Java 8以后,关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N,对于64位JVM来说,元空间的默认初始大小是20.75MB,默认的元空间的最大值是无限。MaxMetaspaceSize用于设置metaspace区域的最大值,这个值可以通过mxbean中的MemoryPoolBean获取到,如果这个参数没有设置,那么就是通过mxbean拿到的最大值是-1,表示无穷大。

由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M

      1.3.3 定位手段:根据所报异常类型结合实际业务情况调整各区域大小

      1.4本机直接内存溢出(-XX:MaxDirectMemorySize 若不设置默认与-Xmx一致)

      1.4.1标识: java.lang.OutOfMemoryError:at.sun.msc.Unsafe.allocateMmory(Native Method)

      1.4.2 产生原因:使用DirectByteBuffer分配内存操作,但是xDirectMemorySize不足,如:nio操作可能引起此异常

      1.4.3定位手段,查看异常,调整参数,在设置堆内存的时候注意预留直接内存

 二 、StackOverflowError(-Xss)出现几率小

       2.1标识:StackOverflowError

       2.2产生的原因:当线程申请的栈深度大于虚拟机所允许的深度。两种情况1.-Xss所设置值过小,2.定义了大量的本地变量

      定位手段:根据异常设置-Xss大小,查看代码中是否有递归用的不合理之处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值