赞
踩
一般来说,绝大部分Java的内存溢出都属于堆溢出。原因是因为大量对象占据了堆空间,这些对象都持有强引用导致无法回收,当对象大小之和大于Xmx参数指定的堆空间时就会发生堆溢出;
解决办法
在Java的NIO中,支持直接内存的使用,通过Java代码获得一块堆外的内存空间。直接内存的申请速度一般比堆内存慢,但是访问速度快于堆内存。
对于那些可复用的,并且会被经常访问的空间使用直接内存可以提高系统性能。直接内存没有被JVM完全托管若使用不当容易触发直接内存溢出导致宕机;
public class DirectBufferOOM {
public static void main(String[] args) {
for (int i = 0; i <1024 ; i++) {
ByteBuffer.allocateDirect(1024*1024);
System.out.println(i);
// System.gc();
}
}
}
直接内存不一定能够触发GC(除非直接内存使用量达到了-XX:MaxDirectMemorySize),所以保证直接内存不溢出的方法是:
如果堆内存少有GC发生,但是直接内存申请频繁会容易导致直接内存溢出;
每一个现成的开启都要占用系统内存,当线程数量太多时,有可能导致OOM,由于线程的栈空间也是在堆外分配的,因此和直接内存非常相似。如果想让系统支持更多的线程应该使用一个较小的堆空间;
永久区是存放类元数据的区域,如果一个系统定义了太多的类型,会导致永久区溢出;
GC是内存回收的关键,如果GC效率低下,系统性能会受到严重影响;如果系统堆空间太小,GC所占用的事件会较多,回收释放的内存较少。
根据GC占有的系统时间、释放内存大小,虚拟机会评估GC效率,一旦认为效率过低就会直接抛出OOM异常;一般情况虚拟机会检查:
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。