理解JVM内存区域有利于更好的java编程,java中最常见的OutOfMemoryError异常就是与JVM的内存区域有关。
JVM内存模型分为以下5类:
1.程序计数器
2.本地方法栈
3.java虚拟机栈
4.java堆
5.方法区(包括常量池)
以上五个区域还可以再分为两大类:线程私有区域和线程共有区域
程序计数器、本地方法栈、java虚拟机栈属于线程私有区域,java堆和方法区属于线程共有区域,如下图所示:
线程私有区域:在线程启动的时候被初始化,一旦线程结束将会销毁。
线程共有区域:所有的线程都会访问到,JVM启动时被初始化,JVM关闭时被销毁。
1.程序计数器
在基本的计算机体系结构中,程序计数器跟踪着指令的执行,就像一个指向当前线程所执行的字节码行号的指针。当每个线程创建的时候都会创建程序计数器,所以该区域是线程私有的。当线程执行的是native方法,该计数器的值为空。该区域没有内存溢出(OutOfMemoryError)异常。
2.java虚拟机栈
JVM栈用于存储java方法执行的内存模型。每个方法被执行的时候都会创建一个栈帧。
如果线程请求的栈深度大于虚拟机的深度将会抛StackOverflowError
如果虚拟机在动态扩展栈时无法获取足够的内存空间将会抛OutOfMemoryError异常
3.本地方法栈
JVM支持本地方法,可以为每个线程分配本地方法栈。如果本地方法不能被JVM加载就不需要本地方法栈。该区域与JVM栈作用相似也会抛StackOverflowError、OutOfMemoryError异常。
4.方法区
方法区是java堆的一个逻辑部分,相对而言垃圾回收再这个区域比较少。运行时常量池也是方法区的一部分。当方法区无法满足内存分配需求时将会抛OutOfMemoryError异常
5.java堆
堆区域用于存储实例对象和数组,它被所有线程共享,也是垃圾回收器发挥作用的地方。如果堆中没有内存可分配,将会抛OutOfMemoryError异常
参考:
1.http://javapapers.com/core-java/java-jvm-run-time-data-areas/#Program_Counter_PC_Register