`

JVM内存模型

 
阅读更多

内容摘自周志明〈深入理解Java虚拟机〉第一版

Java虚拟机管理的内存包括:

  1. 程序计数器: 每个线程都需要独立的程序计数器,各线程之间不相互影响,此区域是虚拟机中唯一不会出现OutOfMemoryError的区域
  2. 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)
     
  3. 本地方法栈:与虚拟机栈类似,为虚拟机使用到的native方法服务.
  4. 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)
     
  5. Java方法区:它用于存储类信息,常量,静态变量,即时编译后的代码等数据.它也被称作永久代(Permanent Generation),它包含运行时常量池。运行时向常量池中大量添加内容或者动态产生大量的类都会导致OutOfMemoryError。如下:
    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();
    		}
    	}
    }
     Eclipse下输出并非像书上写的有OutOfMemoryError: PermGen space。而是:
    Create New Classes count is 99004
    Exception in thread "main" 
    Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
     

最后,直接内存不是虚拟机运行时数据去的一部分,不受Java堆大小的限制.但是它依然有可能会被使用到并且导致OutOfMemoryError,它受到本机总内存的限制.

 

最后,即使是最简单的程序访问,也会涉及到Java堆,栈,方法区三个最重要的内存区域之间的关联关系

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics