OOM可能发生在哪些区域上

根据 javadoc 的描述,OOM 是指JVM 的内存不够用了,同时垃圾回收器也无法提供更多的内存。从描述中可以看到,在JVM抛出OutOfMemoryError之前,垃圾收集器一般会先尝试回收内存。在jvm的哪些区域会发生OOM的情况呢?

第一 , 堆内存。堆内存不足是常见的发送OOM的原因之一,如果在堆中没有内存能都完成对象实例的内存分配,并且堆无法扩展时,将抛出 OOM 异常。当前主流的JVM可以通过-Xmx和-Xms来控制堆内存的大小,发生堆上OOM的可能是存在内存泄漏,也可能是对大小分配不合理。

第二 , Java虚拟机栈和本地方法栈,这两个区域的区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务,在内存分配异常上是相同的。
在JVM规范中,对Java虚拟机栈规定了两种异常:

  1. 如果线程请求的栈大于所分配的栈的大小,则抛出StackOverFlowError错误,比如进行了一个不会停止的递归调用;
  2. 如果虚拟机栈是可以动态扩展的,扩展时无法申请到足够的内存,则抛出OutOFMemoryError错误。

第三 , 直接内存。直接内存虽然不是虚拟机运行时数据区的一部分,但既然是内存,就会收到物理内存的限制。

第四 , 方法区。随着Metaspace元数据区的引入,方法区的OOM错误信息也变成了“java.lang.OutOfMemotyError:Metaspace”.对于旧版本的Orcal JDK,由于永久代的大小有限,而Jvm对永久代的垃圾回收并不是很积极,如果王永久代不断的写入数据,例如:String.Intern()的调用,在永久代占用太多空间导致内存不足,也会出现OOM的问题,对应的错误信息为"java.lang.OutOfMemoryError:PermGen space"

jvm发生OOM区域.jpg

# java  jvm 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×