日常问题处理中常见的内存溢出类型及应对分析

日常问题处理中遇到的内存溢出和JVM参数优化,简单记录一下内存溢出的类型和初步应对分析。

 

处理问题的思路和角度各有不同,希望这篇文章可以抛砖引玉。

 

图片

 

一、堆内存溢出

 

java.lang.OutOfMemoryError: ......java heap space.....

 

对于堆内存溢出,很显然是需要考虑调整堆内存大小,对于JVM启动堆内存,在非64位下只能够设置到4G,但是在64位下可以设置到8G内存或者更大都没有问题。但是建议最多设置到8G,如果对内存设置太大,进行Full GC的时候本身也相对缓慢。

 

如果设置了一个比较大的值,还出现堆内存溢出,那么就是前面一篇讲流控文章谈到的,即出现了大数据量并且长耗时的调用,直接导致内存一直被占用,同时在短时间无法释放,也无法进行垃圾回收。在这种情况下就必须要对这种业务场景和调用方法进行控制。减少每次调用的数据量或缩短优化处理时间。

 

在堆内存这个溢出之前,可能系统会提前先报错关键字为:

java.lang.OutOfMemoryError:GC over head limit exceeded

 

这种情况是当系统处于高频的GC状态,而且回收的效果依然不佳的情况,就会开始报这个错误,这种情况一般是产生了很多不可以被释放的对象,有可能是引用使用不当导致,或申请大对象导致,但是java heap space的内存溢出有可能提前不会报这个错误,也就是可能内存就直接不够导致,而不是高频GC.

 

图片

 

 

二、PermGen的溢出

 

java.lang.OutOfMemoryError: PermGen space

 

原因:系统的代码非常多或引用的第三方包非常多、或代码中使用了大量的常量、或通过intern注入常量、或者通过动态代码加载等方法,导致常量池的膨胀,虽然JDK 1.5以后可以通过设置对永久带进行回收,但是我们希望的是这个地方是不做GC的,它够用就行,所以一般情况下今年少做类似的操作。

 

注意在JDK1.9已经没有PermSize设置参数,而是被XX:MetaspaceSize替代。主要如果出现PermGen溢出,一般情况都是代码本身有问题需要优化。

 

图片

 

三、使用ByteBuffer中的allocateDirect()的时候会出现内存溢出

 

java.lang.OutOfMemoryError: Direct buffer memory

 

如果你在直接或间接使用了ByteBuffer中的allocateDirect方法的时候,而不做clear的时候就会出现类似的问题,常规的引用程序IO输出存在一个内核态与用户态的转换过程,也就是对应直接内存与非直接内存。

 

如果常规的应用程序你要将一个文件的内容输出到客户端需要通过OS的直接内存转换拷贝到程序的非直接内存(也就是heap中),然后再输出到直接内存由操作系统发送出去,而直接内存就是由OS和应用程序共同管理的,而非直接内存可以直接由应用程序自己控制的内存,jvm垃圾回收不会回收掉直接内存这部分的内存。

 

如果经常有类似的操作,可以考虑设置参数:-XX:MaxDirectMemorySize

 

图片

 

四、堆栈内存溢出

 

java.lang.StackOverflowError

 

这个参数直接说明一个内容,就是-Xss太小了,我们申请很多局部调用的栈针等内容是存放在用户当前所持有的线程中的,线程在jdk 1.4以前默认是256K,1.5以后是1M,如果报这个错,只能说明-Xss设置得太小。

 

图片

 

五、线程分配内存溢出错误

 

java.lang.OutOfMemoryError: unable to create new native thread

 

上面第四种溢出错误,已经说明了线程的内存空间,其实线程基本只占用heap以外的内存区域,也就是这个错误说明除了heap以外的区域,无法为线程分配一块内存区域了,这个要么是内存本身就不够,要么heap的空间设置得太大了,导致了剩余的内存已经不多了,而由于线程本身要占用内存,所以就不够用了。

图片

 

六、地址空间不够导致内存溢出

 

java.lang.OutOfMemoryError: request {} byte for {}out of swap

 

这类错误一般是由于地址空间不够而导致。

 

六大类常见溢出已经说明JVM中99%的溢出情况,要逃出这些溢出情况非常困难,除非一些很怪异的故障问题会发生,比如由于物理内存的硬件问题,导致了code cache的错误(在由byte code转换为native code的过程中出现,但是概率极低),这种情况内存 会被直接crash掉,类似还有swap的频繁交互在部分系统中会导致系统直接被crash掉,OS地址空间不够的话,系统根本无法启动。

 

另外GC本身是需要内存空间的,因为在运算和中间数据转换过程中都需要有内存,所以你要保证GC的时候有足够的内存哦,如果没有的话GC的过程将会非常的缓慢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值