论述题 6.  如何能使JVM的堆、栈和持久代(perm)发生内存溢出?
【正确答案】在Java语言中,通过new实例化的对象都存储在堆空间中,因此,只要不断地用new实例化对象且一直保持对这些对象的引用(垃圾回收器无法回收),实例化足够多的实例出来就会导致堆溢出,示例代码如下:
   List<Object>1=new ArrayList<Object>();
   while(true)
   1.add(new Object());
   上面这段代码会一直不停地创建Object的对象,并存储在List里面。因为创建出来的对象一直被引用,所以垃圾回收器无法进行回收,在创建一定的数量后,就会出现堆溢出。
   2)在方法调用的时候,栈用来保存上下文的一些内容。由于栈的大小是有上限的,当出现非常深层次的方法调用的时候,就会把栈的空间用完,最简单的栈溢出的代码就是无限递归调用,示例代码如下:
   public class Test
   {
   public static void f()
   {
   System.out.println("Hello");
   f();
   }
   public static void main(String[]args)
   {
   f();
   }
   }
   程序运行的过程中会不断地输出“Hello”,输出一会儿后就会抛出java.lang.StackOverflowError异常。
   3)持久代。在Java语言中,当一个类第一次被访问的时候,JVM需要把类加载进来,而类加载器就会占用持久代的空间来存储classes信息,持久代中主要包含以下的信息:类方法、类名、常量池和JVM使用的内部对象等。当JVM需要加载一个新的类的时候,如果持久代中没有足够的空间,此时就会抛出Java.Lang.OutOfMemoryError:PermGen Space异常。所以,当代码加载足够多类的时候就会导致持久代溢出。当然,并不是所有的Java虚拟机都有持久代的概念。
【答案解析】