OOM 常见原因及解决方案

一、造成原因

1、内存泄漏

由于长期保持某些资源的引用,垃圾回收器无法回收它,从而使该资源不能够及时释放,也称为内存泄露。因而尽量不要将所有引用都使用为强引用,可以在合适的地方使用弱引用和软引用。

2、超大对象

保存多个耗用内存过大或当加载单个超大的对象时,该对象的大小超过了当前剩余的可用内存空间。比如查询数据库中的数据,一次查询过多,直接导致内存溢出了。因此查询数据库如果数据过多尽量使用分页查询。

3、其他原因

比如是否存在死循环,大循环重复产生对象,是否有集合对象使用完之后,依然被引用着,导致无法清除,是否使用了不恰当的数据结构,导致占用空间过大等等。

二、解决方案

1、修改JVM启动参数,直接增加内存

  • -Xms、-Xmx
    设置进程堆内存的最小值和最大值。

  • -Xmn
    设置堆内新生代的大小。通过这个值我们也可以得到老生代的大小:-Xmx减去-Xmn

  • -Xss
    设置每个线程可使用的内存大小(JDK5.0以后每个线程堆栈大小为1M)。

  • -XX:PermSize、-XX:MaxPermSize
    分配用来设置永久代的最小大小和最大大小。(Java 8以后移除了永久代,取而代之的是本地元空间Metaspace,大小由-XX:MetaspaceSize和-XX:MaxMetaspaceSize调节。)

  • -XX:MaxTenuringThreshold
    设置转入老生代的存活次数。如果是0,则直接跳过新生代进入老生代。

  • -XX:NewRatio
    设置老生代和新生代的比值,例如该值为3,则表示新生代与老生代比值为1:3。

  • -XX:+HeapDumpOnOutOfMemoryError
    表示当JVM发生OOM时,自动生成dump文件

示例配置:
JAVA_OPTS="-server -Xmx1024m -Xms=1024m -Xss512k -XX:+HeapDumpOnOutOfMemoryError"

2、找出可能发生内存溢出的位置,并解决

  • 检查代码中是否有死循环或递归调用。
  • 检查是否有大循环重复产生新对象实体。
  • 检查对数据库查询中,是否有一次获得全部数据的查询。
  • 检查List、Map等集合对象是否有使用完后,未清除的问题。
  • 使用内存查看工具动态查看内存使用情况。
# Java  JVM 

评论

Your browser is out-of-date!

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

×