侧边栏壁纸
博主头像
侯秀荣

贪婪和恐惧是人性的两大弱点,
人类几万年,人性也没进步1厘米。

  • 累计撰写 172 篇文章
  • 累计收到 3 条评论

常见JVM错误代码示例

2018-11-3 / 0 评论 / 1523 阅读

一、常见JVM异常示例代码

package com.houxr.jvm.study;

import com.google.common.collect.Lists;

import org.springframework.cglib.proxy.Enhancer;

import org.springframework.cglib.proxy.MethodInterceptor;

import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;

/

  jvm test

 
需要设置 VM options : -Xms1m -Xmx1m -XX:MaxMetaspaceSize=5M

  https://blog.csdn.net/soonfly/article/details/70147205

 
@author houxiurong

  @date 2018-11-01

 
/

public class JvmTest extends ClassLoader {

    /


      List是动态增长的,因此容量不够了,就会扩容,一旦空闲内存分配完毕,请求不到其他内存,就抛出OutOfMemoryError。

     
<p>

      模拟OutOfMemoryError 堆溢出错误

     
java.lang.OutOfMemoryError: Java heap space

     */

    public static void outOfMemoryError() {

        ArrayList list = Lists.newArrayList();

        while (true) {

            list.add(new JvmTest());

        }

    }

    /

      不断往堆中塞新增的StringBuffer对象,堆满了就直接溢出了

     
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

     */

    public static void heapOverFlow() {

        int count = 10000;

        int size = 0;

        while (true) {

            StringBuffer buffer = new StringBuffer();

            for (int i = 0; i < count; i++) {

                buffer.append(i);

            }

            System.out.println("=======================" + (++size));

        }

    }

    /

      栈溢出错误

     
程序详解:

      执行main函数会创建一个线程,同时创建一个虚拟机栈(栈内存)

     
调用JvmTest.stackOverflowError()时,会对 stackOverflowError()进行压栈操作,将 stackOverflowError()运行期数据的数据集

      保存到栈帧(Stack Frame)(如果main方法里面调用多个方法,会执行多个压栈操作)。

     
stackOverflowError()递归调用时,都会产生一个新的栈帧区块,这时就会连续的产生新的栈帧区块

      当栈内存超过系统配置的栈内存-Xss:2048,就会出现java.lang.StackOverflowError异常.这也是为什么对于需要谨慎使用递归调用的原因!

     
Stack length:11131

      <p>

     
Exception in thread "main" java.lang.StackOverflowError

     /

    public void stackOverflowError() {

        STACK_COUNT++;

        stackOverflowError();

    }

    private Integer STACK_COUNT = 1;

    /


      运行时常量池导致内存溢出

     
JDK1.7 Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

      JDK1.8 CMS Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

     
/

    public static void runtimeConstantPoolOOM1() {

        //List保持常量池引用,避免Full GC回收常量池行为

        List<String> list = Lists.newArrayList();

        int i = 0;

        while (true) {

            list.add(String.valueOf(i++).intern());

        }

    }

    /*

     
运行时常量溢出-问题思考

      String.intern()是一个Native方法,

     
作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,

      则返回代表池中这个字符串的String对象,否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。

     
/

    public static void runtimeConstantPoolOOM2() {

        String str1 = new StringBuilder("土豆丝").append("不加辣").toString();

        String str11 = "土豆丝不加辣";

        //JDK 1.6 false JDK 1.7 true JDK 1.8 false

        System.out.println("========str1======" + (str1.intern() == str1));

        // JDK 1.8 true

        System.out.println("========str11======" + (str1.intern().equals(str11)));

        String str2 = new StringBuilder("ja").append("va").toString();

        String str22 = str2.intern();

        //JDK 1.6 false JDK 1.7 true JDK 1.8 false

        System.out.println("========str2======" + (str2 == str22));

    }

    /


      方法区溢出

     
<p>

      MetaSpace 溢出

     
方法区的内存溢出 中, JDK8 没有了永久代的概念

      在JDK8中,使用了MetaSpace的区域来存放Class的相关信息,

     
当 MetaSpace 内存空间不足时, 会抛出 java.lang.OutOfMemoryError: Metaspace异常.

      $ -XX:MaxMetaspaceSize=5M

     
CGLIB直接操作字节码运行时,生成大量的动态类

     */

    public static void jdk8MethodAreaOOM() {

        while (true) {

            Enhancer enhancer = new Enhancer();

            enhancer.setSuperclass(JvmTest.class);

            enhancer.setUseCache(false);

            enhancer.setCallback(new MethodInterceptor() {

                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

                    return methodProxy.invokeSuper(o, objects);

                }

            });

            enhancer.create();

        }

    }

    public static void main(String[] args) throws Throwable {

//        模拟OutOfMemoryError 堆溢出错误

//        JvmTest.outOfMemoryError();

//        JvmTest.heapOverFlow();

        //栈溢出

        JvmTest jvmTest = new JvmTest();

        try {

            jvmTest.stackOverflowError();

        } catch (Throwable e) {

            System.out.println("========Stack length:" + jvmTest.STACK_COUNT);

            throw e;

        }

//        运行时常量池导致内存溢出

//        JvmTest.runtimeConstantPoolOOM1();

//        JvmTest.runtimeConstantPoolOOM2();

        //jvm 8 永久代去掉使用 MetaSpace

//        JvmTest.jdk8MethodAreaOOM();

    }

}



二、调试上面代码最好在IDEA或者Eclipse中设置如下参数,会有更好的效果。


-Xms5m -Xmx5m -XX:MetaspaceSize=5m -XX:MaxMetaspaceSize=5M -Xss256k -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintClassHistogram -XX:+HeapDumpOnOutOfMemoryError

jvm.png

评论一下?

OωO
取消