深入JVM内核(七)

JAVA 2015-12-12

这里我们将对JVM中的堆进行详细分析。

内存溢出(OOM)的原因 在JVM中,内存区间包括:堆,永久区,线程栈和直接内存 1.而内存溢出的原因是占用大量堆空间,导致直接溢出,例如:

import java.util.ArrayList;
 public class Test {
    public static void main(String args[]){
        ArrayList<byte[]> list=new ArrayList<byte[]>();
        while(true){
            list.add(new byte[1024*1024]);
        }
    }
}

抛出异常:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

解决方法:可以手动设置增大堆空间,及时释放内存

再看一个例子:

import java.util.HashMap;
public class Test {
    public static void main(String args[]){
        for(int i=0;i<100000;i++){
            CglibBean bean = new CglibBean("geym.jvm.ch3.perm.bean"+i,new HashMap());         
        }
    }
}

注:CGLib (Code Generation Library) 是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。

抛出异常:Caused by: java.lang.OutOfMemoryError: PermGen space 可以输出详细内存信息查看,解决方法:增大Perm区,允许Class回收 2.还有一种情况是栈溢出 这里的栈溢出指,在创建线程的时候,需要为线程分配栈空间,这个栈空间是向操作系统请求的,如果操作系统无法给出足够的空间,就会抛出OOM 看一个例子: 以 -Xmx1g -Xss1m 运行

  public class Test {
    public static class SleepThread implements Runnable{
        public void run(){
            try {
                Thread.sleep(10000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String args[]){
        for(int i=0;i<1000000;i++){
            new Thread(new SleepThread(),"Thread"+i).start();
            System.out.println("Thread"+i+" created");
        }
    }
}

抛出异常:Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread 解决方法:减少堆内存,减少线程栈大小

3.还有一种内存溢出是直接内存溢出,即ByteBuffer.allocateDirect()无法从操作系统获得足够的空间 在 -Xmx1g -XX:+PrintGCDetails 下运行

import java.nio.ByteBuffer;
public class Test {
    static int i=0;
    public static void main(String args[]){
        while(true){
            ByteBuffer.allocateDirect(1024*1024);
            System.out.println(i++);
            System.gc();
        }
    }
}

结果抛出异常:Exception in thread "main" java.lang.OutOfMemoryError 而此时堆空间还有富余! 解决方法:减少堆内存,有意触发GC

以上就是内存溢出的三种情况。


本文由 Tony 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

赏个馒头吧