内容摘自周志明〈深入理解Java虚拟机〉第一版
Java虚拟机管理的内存包括:
- 程序计数器: 每个线程都需要独立的程序计数器,各线程之间不相互影响,此区域是虚拟机中唯一不会出现OutOfMemoryError的区域
- Java虚拟机栈:也是线程私有。每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法被调用直至执行完成的过程,对应一个栈帧在虚拟机栈中从入栈到出栈的过程.以下例子可以引起StackOverflowError:
输出:public class TestStack { private static int count=0; public static void recursion() throws InterruptedException{ count++; recursion(); } public static void main(String[] arg){ try{ recursion(); }catch(Throwable e){ System.out.println("deep of stack is "+count); e.printStackTrace(); } } }
deep of stack is 9936 java.lang.StackOverflowError at javatuning.ch5.memory.TestStack.recursion(TestStack.java:13)
- 本地方法栈:与虚拟机栈类似,为虚拟机使用到的native方法服务.
- Java堆:所有线程共有的一块内存区域,所有的对象实例以及数组都要在堆上分配。以下程序可以导致java.lang.OutOfMemoryError: Java heap space:
输出:public class HeapOOM { static class OOMObject { } public static void main(String[] args) { List<OOMObject> list = new ArrayList<OOMObject>(); while (true) { list.add(new OOMObject()); } } }
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Unknown Source) at java.util.Arrays.copyOf(Unknown Source) at java.util.ArrayList.grow(Unknown Source) at java.util.ArrayList.ensureExplicitCapacity(Unknown Source) at java.util.ArrayList.ensureCapacityInternal(Unknown Source) at java.util.ArrayList.add(Unknown Source) at com.jingshou.jvm.HeapOOM.main(HeapOOM.java:16)
- Java方法区:它用于存储类信息,常量,静态变量,即时编译后的代码等数据.它也被称作永久代(Permanent Generation),它包含运行时常量池。运行时向常量池中大量添加内容或者动态产生大量的类都会导致OutOfMemoryError。如下:
Eclipse下输出并非像书上写的有OutOfMemoryError: PermGen space。而是:public class TestPermMax { public static void main(String args[]) throws CannotCompileException, NotFoundException, InstantiationException, IllegalAccessException{ int i=0; try{ for (i = 1; i <=Integer.MAX_VALUE; i++) { CtClass c = ClassPool.getDefault().makeClass("Geym" + i); c.setSuperclass(ClassPool.getDefault().get("com.jingshou.JavaBeanObject")); Class clz = c.toClass(); JavaBeanObject v=(JavaBeanObject)clz.newInstance(); } }catch(Throwable e){ System.out.println("Create New Classes count is "+i); e.printStackTrace(); } } }
Create New Classes count is 99004 Exception in thread "main" Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
最后,直接内存不是虚拟机运行时数据去的一部分,不受Java堆大小的限制.但是它依然有可能会被使用到并且导致OutOfMemoryError,它受到本机总内存的限制.
最后,即使是最简单的程序访问,也会涉及到Java堆,栈,方法区三个最重要的内存区域之间的关联关系