zoukankan      html  css  js  c++  java
  • JVM学习之常见溢出类型

    Java堆

    所有对象的实例分配都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,sample如下所示:

     1 public class HeapOOM {
     2     
     3     static class OOMObject{}
     4 
     5     /**
     6      * @param args
     7      */
     8     public static void main(String[] args) {
     9         List<OOMObject> list = new ArrayList<OOMObject>();
    10         
    11         while(true){
    12             list.add(new OOMObject());
    13         }
    14     }
    15 
    16 }

    加上JVM参数-verbose:gc -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError,就能很快报出OOM:

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

    并且能自动生成Dump。

    方法区)

        方法区是存放虚拟机加载类的相关信息,如类、静态变量和常量,大小由-XX:PermSize和-XX:MaxPermSize来调节,类太多有可能撑爆永久带:

     1 public class MethodAreaOOM {
     2     
     3     static class OOMOjbect{}
     4 
     5     /**
     6      * @param args
     7      */
     8     public static void main(String[] args) {
     9         // TODO Auto-generated method stub
    10         while(true){
    11             Enhancer eh = new Enhancer();
    12             eh.setSuperclass(OOMOjbect.class);
    13             eh.setUseCache(false);
    14             eh.setCallback(new MethodInterceptor(){
    15 
    16                 @Override
    17                 public Object intercept(Object arg0, Method arg1,
    18                         Object[] arg2, MethodProxy arg3) throws Throwable {
    19                     // TODO Auto-generated method stub
    20                     return arg3.invokeSuper(arg0, arg2);
    21                 }
    22                 
    23             });
    24             eh.create();
    25         }
    26     }
    27 
    28 }

    加上永久带的JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后会报如下异常:

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

    静态变量或常量也会有可能撑爆方法区:

     1 public class ConstantOOM {
     2 
     3     /**
     4      * @param args
     5      */
     6     public static void main(String[] args) {
     7         // TODO Auto-generated method stub
     8         List<String> list = new ArrayList<String>();
     9         int i=0;
    10         while(true){
    11             list.add(String.valueOf(i++).intern());
    12         }
    13     }
    14 
    15 }

    同样加上JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后报如下异常:

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

    3)Java栈和本地方法栈

        栈是存放线程调用方法时存储局部变量表,操作,方法出口等与方法执行相关的信息,栈大小由Xss来调节,方法调用层次太多会撑爆这个区域,samples如下所示:

     1 package com.cutesource;
     2 
     3 public class StackOOM {
     4 
     5     /**
     6      * @param args
     7      */
     8     
     9     private int stackLength = 1;
    10     
    11     public void stackLeak(){
    12         stackLength++;
    13         stackLeak();
    14     }
    15     
    16     public static void main(String[] args) throws Throwable{
    17         // TODO Auto-generated method stub
    18         StackOOM oom = new StackOOM();
    19         try{
    20             oom.stackLeak();
    21         }catch(Throwable err){
    22             System.out.println("Stack length:" + oom.stackLength);
    23             throw err;
    24         }
    25         
    26     }
    27 
    28 }

    设置JVM参数:-Xss128k,报出异常:

    Exception in thread "main" java.lang.StackOverflowError

    打印出Stack length:1007,这里可以看出,在我的机器上128k的栈容量能承载深度为1007的方法调用。当然报这样的错很少见,一般只会出现无限循环的递归中,另外,线程太多也会占满栈区域:

     1 package com.cutesource;
     2 
     3 public class StackOOM {
     4 
     5     /**
     6      * @param args
     7      */
     8     
     9     private int stackLength = 1;
    10     
    11     private void dontStop(){
    12         while(true){
    13             try{Thread.sleep(1000);}catch(Exception err){}
    14         }
    15     }
    16     
    17     public void stackLeakByThread(){
    18         while(true){
    19             Thread t = new Thread(new Runnable(){
    20 
    21                 @Override
    22                 public void run() {
    23                     // TODO Auto-generated method stub
    24                     dontStop();
    25                 }
    26                 
    27             });
    28             t.start();
    29             stackLength++;
    30         }
    31     }
    32     
    33     public static void main(String[] args) throws Throwable{
    34         // TODO Auto-generated method stub
    35         StackOOM oom = new StackOOM();
    36         try{
    37             oom.stackLeakByThread();
    38         }catch(Throwable err){
    39             System.out.println("Stack length:" + oom.stackLength);
    40             throw err;
    41         }
    42         
    43     }
    44 
    45 }

    报出异常:Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread

    不过在windows上运行这个例子要小心,会出现系统假死的情况,有可能需要重启机器才行。

    以上几个例子虽然比较简单,但能很好帮助普通的程序员更加直观的了解Java堆方法区Java栈和本地方法栈

  • 相关阅读:
    Android学习——SAX解析方式
    Android学习——pull解析方式
    Android学习——使用okhttp
    开课第十五周周总结
    顶会热词3
    顶会热词2
    顶会热词1
    配置JAVA环境
    配置mybaits的一些坑
    Maven配置和idea种tomcat配置的一些坑点
  • 原文地址:https://www.cnblogs.com/sunfie/p/5124752.html
Copyright © 2011-2022 走看看