jvm常见内存溢出异常

来源:互联网 发布:喋血街头java 编辑:程序博客网 时间:2024/05/16 17:35

image

上面这幅图就是jvm虚拟机运行时的主要数据区,蓝色部分是线程共享区域,而白色部分就是线程私有区域。

以下例子均在jdk1.7中运行

1.堆内存溢出

/** * VM Args: -Xms2m -Xmx2m * Created by Stay on 2017/5/15  14:50. */public class Base1 {    public static void main(String[] args) {        List<Object> list = new ArrayList<>();        while(true){            list.add(new byte[2 * 1024]);        }    }}result:  Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

-Xms2m 堆内存最小为2m

-Xmx2m 堆内存最大为2m,参数设置一样是为了避免堆自动扩展

我们再加上-XX:+PrintGCDetails 打印出GC回收的过程:

[GC [PSYoungGen: 2047K->504K(2560K)] 2047K->2028K(5120K), 0.0014692 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC [PSYoungGen: 504K->0K(2560K)] [ParOldGen: 1524K->1696K(5120K)] 2028K->1696K(7680K) [PSPermGen: 2776K->2775K(21504K)], 0.0123204 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] [GC [PSYoungGen: 2046K->512K(2560K)] 3743K->4080K(7680K), 0.0009728 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC [PSYoungGen: 512K->0K(2560K)] [ParOldGen: 3568K->3587K(5120K)] 4080K->3587K(7680K) [PSPermGen: 2792K->2792K(21504K)], 0.0063521 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [Full GC [PSYoungGen: 2047K->503K(2560K)] [ParOldGen: 3587K->5066K(5120K)] 5635K->5570K(7680K) [PSPermGen: 2815K->2815K(21504K)], 0.0091229 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [Full GC [PSYoungGen: 2046K->2023K(2560K)] [ParOldGen: 5066K->5056K(5120K)] 7113K->7079K(7680K) [PSPermGen: 2843K->2843K(21504K)], 0.0054760 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC [PSYoungGen: 2046K->2046K(2560K)] [ParOldGen: 5056K->5056K(5120K)] 7102K->7102K(7680K) [PSPermGen: 2843K->2843K(21504K)], 0.0056718 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] [Full GC [PSYoungGen: 2048K->2046K(2560K)] [ParOldGen: 5118K->5118K(5120K)] 7166K->7164K(7680K) [PSPermGen: 2845K->2845K(21504K)], 0.0051912 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [Full GC [PSYoungGen: 2046K->2046K(2560K)] [ParOldGen: 5118K->5106K(5120K)] 7164K->7153K(7680K) [PSPermGen: 2845K->2845K(21504K)], 0.0075618 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] [Full GC [PSYoungGen: 2046K->2046K(2560K)] [ParOldGen: 5119K->5119K(5120K)] 7165K->7165K(7680K) [PSPermGen: 2846K->2846K(21504K)], 0.0056501 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [Full GC [PSYoungGen: 2046K->2046K(2560K)] [ParOldGen: 5119K->5119K(5120K)] 7165K->7165K(7680K) [PSPermGen: 2846K->2846K(21504K)], 0.0051502 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GCException in thread "main"  [PSYoungGen: 2048K->0K(2560K)] [ParOldGen: 5119K->518K(4608K)] 7167K->518K(7168K) [PSPermGen: 2872K->2872K(21504K)], 0.0084184 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] java.lang.OutOfMemoryError: Java heap spaceat jvm.base1.main(base1.java:16)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)Heap PSYoungGen      total 2560K, used 67K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)  eden space 2048K, 3% used [0x00000000ffd00000,0x00000000ffd10c38,0x00000000fff00000)  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000) ParOldGen       total 4608K, used 518K [0x00000000ff800000, 0x00000000ffc80000, 0x00000000ffd00000)  object space 4608K, 11% used [0x00000000ff800000,0x00000000ff8819e0,0x00000000ffc80000) PSPermGen       total 21504K, used 2897K [0x00000000fa600000, 0x00000000fbb00000, 0x00000000ff800000)  object space 21504K, 13% used [0x00000000fa600000,0x00000000fa8d4468,0x00000000fbb00000)

从打印的这些信息就能看出,虽然JVM在尽力的回收,但是也抵挡不住while(true)的威力。

二.栈溢出

/** * VM Args: -Xss128k * Created by Stay on 2017/5/15  15:41. */public class Base2 {    private int stackLength = 1;    public static void main(String[] args) {        Base2 base2 = null;        try {            base2 = new Base2();            base2.stackLeak();        } catch (Throwable e) {            System.out.println("stack length:" + base2.stackLength);            throw e;        }    }    public void stackLeak() {        stackLength++;        stackLeak();    }}

result:

Exception in thread "main" java.lang.StackOverflowErrorstack length:11409.....

Thread api中有一个不常用的构造器 Thread(ThreadGroup group, Runnable target, String name, long stackSize) ,最后一个参数就是每个线程的栈大小的设置

再来个栗子:

/** * Created by Stay on 2017/5/15  16:15. */public class Base3 {    private static int count = 1;    public static void main(String[] args) {        Thread t1 = new Thread(null,new Runnable() {            @Override            public void run() {                try {                    add(1);                } catch (Throwable e) {                    System.out.println(count);                    e.printStackTrace();                }            }            private void add(int i) {                count++;                add(i + 1);            }        },"stackTest");        t1.start();    }}

result:

java.lang.StackOverflowError10472....

在最后加上一个stackSize参数 Thread t1 = new Thread(null,....,"stackTest",1 << 24);

result:

975998java.lang.StackOverflowError....

count最后的值比刚开始大了不少,就是因为我们给每个线程分配的栈空间变大了,但是能创建的线程就变小了,因为总的栈空间没变。这个构造方法一般用的很少。

有些时候我们把jvm只分为两块 堆和栈,这样的分法是比较粗糙的,只能说明大多数程序员最关注的,就是这两块区域,这里所指的栈就是虚拟机栈,或者说是虚拟机中局部变量表部分.

而堆 就是存放对象实例,所有new出来的实例都存放在这里 栈中只是引用堆中的对象。垃圾回收器也是主要管理这个区域,称为GC堆

三.方法区内存溢出(PermGen space)

我们利用字符串的intern()方法进行实验

为了尽快溢出,jvm参数设置永久代参数5M: -XX:PermSize=5m -XX:MaxPermSize=5m

public static void main(String[] args) {List list = new ArrayList();int i = 0;while(true){list.add((String.valueOf(i++)).intern());}}

运行结果如下:OutOfMemoryError后面提示 PermGen space ;改代码在jdk6及以下版本能够报出如下异常,jdk7高版本及以上部分jvm已经逐渐开始取消永久代的原因,只会报出堆内存异常

Exception in thread "main" java.lang.OutOfMemoryError: PermGen spaceat java.lang.String.intern(Native Method)at com.TestSocket.main(TestSocket.java:12)
原创粉丝点击