【Java虚拟机】内存溢出实战

在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(下文称OOM)异常的可能,本节将通过若干实例来验证异常发生的场景。

    测试异常需要设置虚拟机的启动参数,以MyEclipse工具为例,修改如下:Run——>Run Configurations;(修改的参数在代码顶部注释中,这些参数将对实验的结果有直接影响)


Java堆溢出

    Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常。 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import  java.util.ArrayList;
import  java.util.List;
/**    
  * -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
  * 将堆最小值参数-Xms与最大值-Xmx参数设置为一样即可避免堆自动扩展,
  * @author Vanguard
  */    
public  class  TestGC {
     static  class  OOMObject{
     }    
     public  static  void  main(String[] args) {
         List list =  new  ArrayList<>();
         while ( true ){
             list.add( new  OOMObject());
         }
     }    
}

运行结果为:

OutOfMemoryError后紧跟着Java heap space提示堆溢出。

栈溢出

    由于在HotSpot虚拟机中并不区分虚拟机栈和本地方法栈,因此,对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,栈容量只由-Xss参数设定。
    关于虚拟机栈和本地方法栈,在Java虚拟机规范中描述了两种异常: 

  • 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。 

  • 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
  * -Xss128k
  * @author Vanguard
  */
public  class  JavaVMStackSOF {
     private  int  stackLength= 1 ;
     public  void  stackLeak(){
         stackLength++;
         stackLeak();
     }
     public  static  void  main(String[] args) {
         JavaVMStackSOF oom =  new  JavaVMStackSOF();
         try {
             oom.stackLeak();
         } catch (Throwable e){
             System.out.println( "stack length:" +oom.stackLength);
             throw  e;
         }
     }
}

运行结果:

方法区溢出

    运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行。

    String.intern()是一个Native方法,它的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。 

    方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这些区域的测试,基本的思路是运行时产生大量的类去填满方法区,直到溢出。 

    在实际应用中,当前的很多主流框架,如Spring、Hibernate,在对类进行增强时都会用到CGLib这类字节码技术,增强的类越多,就需要越大的方法区来保证动态生成的Class可以加载入内存,若内存不足则引发异常。

转自:http://www.yexiaoquan.com/article/17061301.html

你可能感兴趣的:(【Java虚拟机】内存溢出实战)