JVM异常解析

来源:互联网 发布:mac os x 10.13 镜像 编辑:程序博客网 时间:2024/05/16 05:27

 一.Java虚拟机栈和本地方法栈内存异常探究

     1.如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量时,Java虚拟机会抛出一个StackOverflowError异常

package com.stack.over;/* * 构造自己的实例,不断递归调用自己,当递归的栈深度到达一定的程度,Java虚拟机就会抛出StackOverflowError异常 * VM栈深度设置: -Xss128k     设置栈深度为128K */public class JavaVmStackSOF {    private int stackLength = 1;public void stackLeak(){stackLength++;stackLeak();}public static void main(String[] args) throws Throwable{// TODO Auto-generated method stub        JavaVmStackSOF oom = new JavaVmStackSOF();        try {oom.stackLeak();} catch (Throwable e) {// TODO Auto-generated catch blockSystem.out.println("stack length:" + oom.stackLength);throw e;}}}

运行截图:



2.如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内存去完成扩展,或者在建立新的线程时,没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将会抛出一个OutOfMemoryError

package com.stack.over;/* * 1.Java虚拟机栈设置成可以动态拓展,并且动态拓展已经尝试,仍然无法申请到足够的内存,Java虚拟机就会抛出异常 * 2.Java虚拟机尝试建立新线程时,如果当前已经没有足够的内存去创建新 线程,或操作系统拒绝创建新线程,这时Java虚拟机也会抛出异常 * 注意:此段代码运行将会创建很多线程,让系统变得十分卡慢,直到内存不足,终止运行 */public class JavaVmStackOOM {public void dontstop(){while(true){}}public void stackLeakByThread(){while(true){Thread thread = new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubdontstop();}});thread.start();}}public static void main(String[] args) {// TODO Auto-generated method stub        JavaVmStackOOM oom = new JavaVmStackOOM();        oom.stackLeakByThread();}}

二.Java堆内存异常探究

   1.如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那么Java虚拟机将会抛出一个OutOfMemoryError

package com.heap.over;import java.util.ArrayList;import java.util.List;/* * 1.不断在Java堆中创建对象,并保证对象不会被内存回收,随着while的不断循环执行,对象会越来越多,直至超出Java堆的最大容量 * 2.将JVM的内存参数设置在20M之内,Java堆发生溢出时,Java虚拟机会自动把当前Java堆的内存印象荡复到磁盘中,供后续调试分析:  *  -Xms20m  -Xmx20m  -XX:+HeapDumpOnOutOfMemoryError */public class HeapOOM {public static class OOMObject{}public static void main(String[] args) {// TODO Auto-generated method stub      List<OOMObject> list = new ArrayList<OOMObject>();            while(true){      list.add(new OOMObject());       //对象一直被List集合引用,保证不会被回收      }}}

截图:



三.Java常量池与方法区溢出异常

package com.constantPool.over;import java.util.ArrayList;import java.util.List;/* * 运行时常量池溢出的代码 * 把虚拟机的永久代内存限制起始10M,最大10M:  -XX:PermSize=10M -XX:MaxPermSize=10M * 1.不断循环,产生字符串常量,字符串常量会随整形数字i的增加而不断变化 */public class RuntimeConstantPoolOOM {public static void main(String[] args) {// TODO Auto-generated method stub   //使用List保持着常量池引用,避免Full GC回收常量池行为       List<String> list = new ArrayList<String> ();       //10M的PermSize在Integer范围内足够产生OOM       int i = 0 ;       while(true){       list.add(String.valueOf(i++).intern());       //随i增加不断变化       }}   //jdk1.7开始把字符串常量池罗列到Java堆中,即使这么多对象也不足够让内存撑爆,不会抛出异常,jdk1.6的永久代会抛异常}



原创粉丝点击