天天看点

JVM-内存溢出

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/usr/local/app/oom
           

第一个参数意思是在OOM的时候自动dump内存快照出来,第二个参数是说把内存快照放到哪儿去

可能发生内存溢出的区域

  1. Metaspace区域
  2. 栈内存
  3. 堆内存

一.Metaspace区域

在jvm参数配置中通过以下参数分配限制大小

-XX:MetaspaceSize=512m
-XX:MaxMetaspaceSize=512m
           

Metaspance区域内存溢出的主要两个原因:

  • 第一种原因,上线系统Metaspace区域直接用默认的参数,即根本不设置其大小。这会导致默认的Metaspace区域可能才几十MB而已,此时对于一个稍微大型一点的系统,因为他自己有很多类,还依赖了很多外部的jar包有有很多的类,几十MB的Metaspace很容易就不够了
  • 第二种原因,系统用了cglib之类的技术动态生成一些类,一旦代码中没有控制好,导致你生成的类过于多的时候,就很容易把Metaspace给塞满,进而引发内存溢出。

对于第一种原因推荐的值为512MB,一般够用。

第二种就是控制好使用cglib之类的技术动态生成类,避免过多生成。

Caused by: java.lang.OutOfMemoryError: Metaspace。

二.栈内存

我们是可以手动设置每个线程的虚拟机栈的内存大小的,一般来说现在默认都是给设置1MB

-Xss1024K 
           

或者使用  -XX:ThreadStackSize=1m 设置

一般注意一下代码的编写,避免出现无限制的方法递归,就一般可以避免栈内存的溢出。

java.lang.StackOverflowError

三.堆内存

堆内存发生oom的原因大致是有限的内存中放了过多的对象,而且大多数都是存活的,此时即使GC过后还是大部分都存活,所以要继续放入更多对象已经不可能了,此时只能引发内存溢出问题。

所以一般来说发生内存溢出有两种主要的场景:

1.系统承载高并发请求,因为请求量过大,导致大量对象都是存活的,所以要继续放入新的对象实在是不行了,此时就会引发OOM系统崩溃

2.系统有内存泄漏的问题,就是莫名其妙弄了很多的对象,结果对象都是存活的,没有及时取消对他们的引用,导致触发GC还是无法回收,此时只能引发内存溢出,因为内存实在放不下更多对象了。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space