Java OOM是什么?

南风 2020年10月27日 199次浏览

一、OOM是什么?

堆对象在无法给对象分配内存空间的时候会触发一次Full GC回收垃圾对象,如果在回收了之后还没有足够的空间给新对象,那么就会抛出OOM的异常。java.lang.OutOfMemoryErrorJava堆溢出。

  • 1、java.lang.OutOfMemoryError: Java heap space Java栈溢出
  • 2、java.lang.OutOfMemoryError: PermGen space 运行时常量池溢出和方法区存放Class过多导致溢出。方法区的大小是设定好的,Java8之后将Class信息放到了元空间,并且元空间是可以动态申请扩展
  • 3、java.lang.OutOfMemoryError:unable to create natvie thread 栈空间不足了无法创建新的线程。

总而言之,对象无法GC回收导致新对象无法创建,从而引发OOM异常。

二、什么会导致OOM?

  • 1、静态集合类引起的内存泄漏
    静态集合类的生命周期和类一致,只要类不被回收,集合对象永远都不回收,导致集合越来越大,从而引发堆分配内存不足。
  • 2、HashSet对象属性修改后,导致hashcode()变化,无法调用remove()进行删除操作。
  • 3、各种中间件连接或者需要close()的处理,如果没有close()会导致对象应用一直持有不释放,导致内存激增引发OOM。

对象可达性分析

三、如何分析OOM?

分析MAT可以使用MAT插件,也可以使用Jprofiler(收费性能分析工具),关于MAT的性能分析可以阅读这篇文章 MAT内存泄漏分析

四、如何解决OOM?

 最近,我们的生产环境某个业务出现内存泄漏,引起各种问题,导致真正问题被掩盖,由于OOM导致服务进程宕机,无法注册到Eureka注册中心,整个服务不可用,导致前台业务不可用。
 究其原因,罪魁祸首就是对象使用不当导致业务量增加时,对象持有时间较久,多线程访问时,对象不断积累导致堆区内存不够,Full GC也无法释放释放足够堆区内存,导致OOM.
 那么,这种问题我们应该什么解决,只能增加JVM堆区内存?不一定!我认为有以下几点可以优化:

  • 1、首先应该检查代码,使得对应引用尽可能少,引用时间尽可能短,尽量重用对象;
  • 2、其次适当调整JVM内存;
  • 3、最后增加集群节点,较少并发量,限定服务节点支持的最大并发数,使得耗时任务并发量减少。

(全文完)