JVM在执行Java程序的过程中把他管理的内存划分为若干个不同的数据区域。这些数据区域各有各的用处,各有各的创建与销毁时间。一般来说,JVM所管理的内存将会包含以下几个运行是数据区域
线程私有区域:程序计数器 , Java虚拟机栈 , 本地方法栈
线程共享区域:Java堆,方法区,运行时常量池
程序计数器
程序计数器是比较小的内存空间,当前线程锁执行的字节码的行号指示器。若当前线程执行的是Java方法,计数器记录的是正在执行的JVM字节码指令地址;若当前线程执行的是Native方法,计数器值为空。
程序计数器是唯一一块不会产生OOM异常的区域。
虚拟机栈
虚拟机栈描述的是Java方法执行的内存模型:
每个方法执行的同时都会创建一个栈帧存储局部变量表,操作数栈,方法出口等信息。每个方法从调用直到执行完毕的过程,对象一个栈帧在虚拟机栈的入栈与出栈过程。
生命周期与线程相同:在创建线程的同时创建此线程的虚拟机栈,线程执行结束,虚拟机栈与线程一同被回收。
此区域一共会产生两种异常:
1.若线程请求的栈深度大于JVM允许的深度,抛出StackOverFlowError异常。
2.虚拟机在进行栈的动态扩展是,若无法申请到足够内存,抛出OOM(OutOfMemoryError)异常.
本地方法栈
本地方法(native方法)执行的内存模型,其他与虚拟机栈基本相同。
HotSpot虚拟机中,本地方法栈与虚拟机栈是同一块内存区域。
Java堆(GC堆)
Java堆(Java Heap)是JVM管理的最大内存区域。在JVM启动时创建,所有线程共享此内存,此内存中存放的都是对象实例及数组。
Java堆是垃圾回收器管理的最主要内存区域。Java堆可以处于物理上不连续的内存空间。-Xmx设置堆最大值 , -Xms设置堆最小值
若在堆中没有足够的内存完成对象实例分配并且堆无法再次扩展时。抛出OOM异常。
方法区
用于存储已被JVM加载的类信息,常量,静态变量等数据。JDK8以前,方法区也叫”永久代“,JDK8之后称为元空间(Meta Space)
方法区无法满足内存分配需求时,抛出OOM
运行时常量池
运行时常量池是方法区的一部分,存放字面量与符号引用。
字面量:字符串常量(JDK1.7移到堆中),final常量,基本数据类型的值。
符号引用:类,字段,方法的完全限定名,名称,描述符。