JVM 性能调优

内存溢出(OutOfMemory,简称OOM)
内存溢出问题,包括堆溢出、直接内存溢出、永久区溢出等

A.堆溢出
堆是 Java 程序中最为重要的内存空间,由于大量的对象都直接分配在堆上,因此它也成为
最有可能发生溢出的区间。一般来说,绝大部分Java 的内存溢出都属于这种情况。其原因是因
为大量对象占据了堆空间,而这些对象都持有强引用,导致无法回收,当对象大小之和大于由
Xmx 参数指定的堆空间大小时,溢出错误就自然而然地发生了。
public class SimpleHeapOOM {
public static void main(String args[]){
ArrayList<byte[]> list=new ArrayList<byte[]>();
for(int i=0;i<1024;i++){
list.add(new byte[1024*1024]);
}
}
}

B.直接内存溢出
在 Java 的NIO(New IO)中,支持直接内存的使用,也就是通过Java 代码,获得一块堆
外的内存空间,这块空间是直接向操作系统申请的。直接内存的申请速度一般要比堆内存慢,
实战Java 虚拟机——JVM 故障诊断与性能优化
 206 
但是其访问速度要快于堆内存。因此,对于那些可复用的,并且会被经常访问的空间,使用直
接内存是可以提高系统性能的。但由于直接内存没有被Java 虚拟机完全托管,若使用不当,也
容易触发直接内存溢出,导致宕机。

public class DirectBufferOOM {
public static void main(String args[]) {
for (int i = 0; i < 10000; i++) {
ByteBuffer.allocateDirect(1024 * 1024);
System.out.println(i);
// System.gc();
}
}
}
C.过多线程导致OOM
由于每一个线程的开启都要占用系统内存,因此当线程数量太多时,也有可能导致OOM。
由于线程的栈空间也是在堆外分配的,因此和直接内存非常相似,如果想让系统支持更多的线
程,那么应该使用一个较小的堆空间。
D.永久区溢出
  永久区(Perm)是存放类元数据的区域。如果一个系统定了太多的类型,那么永久区是有
可能溢出的。在JDK 1.8 中,永久区被一块称为元数据的区域替代,但是它们的功能是类似的,
都是为了保存类的元信息。

猜你喜欢

转载自xls9577087.iteye.com/blog/2274339