JVM内存模型(3)、实战各种Java堆栈异常

作者: 编程界的小学生 | 来源:发表于2017-09-06 14:04 被阅读73次

1、说明
本章节直接贴代码看现象。并作解释说明;
本篇会涉及到添加JVM的参数,如下方式即可添加:

Eclipse添加参数方式
鼠标右键-》Run AS-》Run Configurations...

Paste_Image.png

IDEA添加参数方式

Paste_Image.png

选中第一个Edit Configurations...

Paste_Image.png

看不懂参数没关系的,复制粘贴我的进去就好了,后面我会详细介绍。

二、进入正题

1、StackOverFlow异常(栈溢出)
(1)JVM参数
-verbose:gc -Xms10M -Xmx10M -Xss128k -XX:+PrintGCDetails

(2)代码

/**
 * @author TongWei.Chen 2017-09-01 16:21:38
 */
public class HelloStackOverFlow {
    private int counter;

    public void count() {
        counter ++;

        count();
    }

    public static void main(String[] args) {
        System.out.println("HelloStackOverFlow");

        HelloStackOverFlow helloStackOverFlow = new HelloStackOverFlow();

        try {
            helloStackOverFlow.count();
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
}

(3)结果

[GC (Allocation Failure) [PSYoungGen: 2048K->488K(2560K)] 2048K->747K(9728K), 0.0056735 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 
HelloStackOverFlow
Exception in thread "main" java.lang.StackOverflowError
    at jvm.day01.HelloStackOverFlow.count(HelloStackOverFlow.java:10)
.................
Heap
 PSYoungGen      total 2560K, used 1821K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 65% used [0x00000000ffd00000,0x00000000ffe4d658,0x00000000fff00000)
  from space 512K, 95% used [0x00000000fff00000,0x00000000fff7a020,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 259K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 3% used [0x00000000ff600000,0x00000000ff640c70,0x00000000ffd00000)
 Metaspace       used 3575K, capacity 4502K, committed 4864K, reserved 1056768K
  class space    used 392K, capacity 394K, committed 512K, reserved 1048576K

结果看不懂没关系,后面篇幅我都会讲解到,现在只需要看到出现了StackOverflowError即可。

(4)分析
为什么出现StackOverflowError?
很简单,因为我们搞了个相当于死循环一样的程序,一直往栈里面压counter这个变量,最终把栈压爆了。

2、OutOfMemory(OOM,堆溢出)
(1)参数
-verbose:gc -Xms10M -Xmx10M -Xss128k -XX:+PrintGCDetails

(2)代码

import java.util.ArrayList;
import java.util.List;

/**
 * @author TongWei.Chen 2017-09-01 16:01:16
 */
public class HelloHeapOutOfMemory {

    public static void main(String[] args) {
        System.out.println("HelloHeapOutOfMemory");

        List<Person> persons = new ArrayList<Person>();
        int counter = 0;
        while (true) {
            persons.add(new Person());
        }
    }
}

class Person {}

(3)结果

[GC (Allocation Failure) [PSYoungGen: 2045K->488K(2560K)] 2045K->762K(9728K), 0.0062203 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
HelloHeapOutOfMemory
[GC (Allocation Failure) [PSYoungGen: 2517K->504K(2560K)] 2791K->2164K(9728K), 0.0050936 secs] [Times: user=0.02 sys=0.03, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2552K->504K(2560K)] 4212K->3805K(9728K), 0.0057710 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2552K->488K(2560K)] 5853K->5871K(9728K), 0.0055545 secs] [Times: user=0.05 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 488K->0K(2560K)] [ParOldGen: 5383K->4878K(7168K)] 5871K->4878K(9728K), [Metaspace: 3513K->3513K(1056768K)], 0.1135539 secs] [Times: user=0.11 sys=0.01, real=0.11 secs] 
[GC (Allocation Failure) [PSYoungGen: 2048K->512K(2560K)] 6926K->6901K(9728K), 0.0040402 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 512K->0K(2560K)] [ParOldGen: 6389K->5947K(7168K)] 6901K->5947K(9728K), [Metaspace: 3513K->3513K(1056768K)], 0.0791164 secs] [Times: user=0.14 sys=0.00, real=0.08 secs] 
[Full GC (Ergonomics) [PSYoungGen: 1838K->777K(2560K)] [ParOldGen: 5947K->6970K(7168K)] 7785K->7747K(9728K), [Metaspace: 3513K->3513K(1056768K)], 0.1366169 secs] [Times: user=0.14 sys=0.00, real=0.14 secs] 
[Full GC (Allocation Failure) Exception in thread "main" [PSYoungGen: 777K->777K(2560K)] [ParOldGen: 6970K->6950K(7168K)] 7747K->7728K(9728K), [Metaspace: 3513K->3513K(1056768K)], 0.1141202 secs] [Times: user=0.14 sys=0.02, real=0.11 secs] 
java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3210)
    at java.util.Arrays.copyOf(Arrays.java:3181)
    at java.util.ArrayList.grow(ArrayList.java:261)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
    at java.util.ArrayList.add(ArrayList.java:458)
    at jvm.day01.HelloHeapOutOfMemory.main(HelloHeapOutOfMemory.java:17)
Heap
 PSYoungGen      total 2560K, used 858K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 41% used [0x00000000ffd00000,0x00000000ffdd6ba0,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 6950K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 96% used [0x00000000ff600000,0x00000000ffcc9ae0,0x00000000ffd00000)
 Metaspace       used 3545K, capacity 4504K, committed 4864K, reserved 1056768K
  class space    used 393K, capacity 396K, committed 512K, reserved 1048576K

出现了java.lang.OutOfMemoryError: Java heap space

(4)分析
也很简单,我们一直往堆内存里面创建Person对象,并且把对象一直追加到List里,这样垃圾回收器认为是有用对象,所以不会轻易回收,最终内存爆掉了。我设置的参数是说堆内存分配10MB大小,所以这样才能出现结果。否则堆太大,需要跑好久的程序才会爆掉。

3、ConstantOutOfMemory(常量池溢出)
(1)参数
-verbose:gc -Xms10M -Xmx10M -Xss128k -XX:+PrintGCDetails

(2)代码

import java.util.ArrayList;
import java.util.List;

/**
 * @author TongWei.Chen 2017-09-01 16:27:58
 */
public class HelloConstantOutOfMemory {

    public static void main(String[] args) {
        try {
            List<String> strings = new ArrayList<>();
            int item = 0;

            while (true) {
                strings.add(String.valueOf(item ++).intern());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

}

(3)结果

.......
[Full GC (Ergonomics) [PSYoungGen: 2047K->2047K(2560K)] [ParOldGen: 7149K->7149K(7168K)] 9197K->9197K(9728K), [Metaspace: 3512K->3512K(1056768K)], 0.0478489 secs] [Times: user=0.17 sys=0.00, real=0.05 secs] 
[Full GC (Ergonomics) Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
[PSYoungGen: 2047K->2047K(2560K)] [ParOldGen: 7151K->7151K(7168K)] 9199K->9199K(9728K), [Metaspace: 3512K->3512K(1056768K)], 0.0478559 secs] [Times: user=0.13 sys=0.00, real=0.05 secs] 
[Full GC (Ergonomics)   at java.lang.Integer.toString(Integer.java:403)
    at java.lang.String.valueOf(String.java:3099)
    at jvm.day01.HelloConstantOutOfMemory.main(HelloConstantOutOfMemory.java:17)
[PSYoungGen: 2047K->0K(2560K)] [ParOldGen: 7167K->696K(7168K)] 9215K->696K(9728K), [Metaspace: 3537K->3537K(1056768K)], 0.0088147 secs] [Times: user=0.05 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 2560K, used 57K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 2% used [0x00000000ffd00000,0x00000000ffd0e510,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 7168K, used 696K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 9% used [0x00000000ff600000,0x00000000ff6ae090,0x00000000ffd00000)
 Metaspace       used 3544K, capacity 4502K, committed 4864K, reserved 1056768K
  class space    used 392K, capacity 394K, committed 512K, reserved 1048576K

出现了Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

(4)分析
依旧很简单。我们一直往常量池里追加item对应的这个值。并加到List中,所以常量池爆掉了。道理同OOM的分析

若有兴趣,欢迎来加入群,【Java初学者学习交流群】:458430385,此群有Java开发人员、UI设计人员和前端工程师。有问必答,共同探讨学习,一起进步!
欢迎关注我的微信公众号【Java码农社区】,会定时推送各种干货:


qrcode_for_gh_577b64e73701_258.jpg

相关文章

网友评论

    本文标题:JVM内存模型(3)、实战各种Java堆栈异常

    本文链接:https://www.haomeiwen.com/subject/nqamjxtx.html