java虚拟机所管理的内存分为以下几个数据区域:
方法区(method area)
虚拟机栈(VM Stack)
本地方法栈(Native Method Stack)
堆区(Heap)
程序计数器(Program Counter Register)
程序计数器:
是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
分支、循坏、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
线程切换后能恢复到正确的执行位置,是因为每条线程都有一个独立的程序计数器,且各条线程之间的计数器互相不影响。
如果线程正在执行一个java方法,计数器则记录正在执行的虚拟机字节码指令的地址。
如果正在执行的是Native方法,这个计数器值为空(Undefined)
这个内存区域是惟一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
虚拟机栈:
虚拟机栈也是属于线程私有,生命周期和线程相同。它描述的是java方法执行的内存模型;
每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
虚拟机栈中有一局部变量表,存放编译期可知的各种基本数据类型。其中64位长度的long和double类型的数据会占用两个局部变量空间,其余的只占一个。
局部变量表所需要的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是确定的,且方法运行期间不会改变局部变量大小。
这个区域有两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,当扩展到无法申请到足够的内存时会抛OutOfMemoryError异常。
本地方法栈:
它和虚拟机栈发挥的作用是非常类似的,只是它服务于虚拟机使用到的Native方法,而虚拟机栈则为虚拟机执行的java方法服务。
方法区(method area)
虚拟机栈(VM Stack)
本地方法栈(Native Method Stack)
堆区(Heap)
程序计数器(Program Counter Register)
程序计数器:
是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
分支、循坏、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
线程切换后能恢复到正确的执行位置,是因为每条线程都有一个独立的程序计数器,且各条线程之间的计数器互相不影响。
如果线程正在执行一个java方法,计数器则记录正在执行的虚拟机字节码指令的地址。
如果正在执行的是Native方法,这个计数器值为空(Undefined)
这个内存区域是惟一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
虚拟机栈:
虚拟机栈也是属于线程私有,生命周期和线程相同。它描述的是java方法执行的内存模型;
每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
虚拟机栈中有一局部变量表,存放编译期可知的各种基本数据类型。其中64位长度的long和double类型的数据会占用两个局部变量空间,其余的只占一个。
局部变量表所需要的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是确定的,且方法运行期间不会改变局部变量大小。
这个区域有两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,当扩展到无法申请到足够的内存时会抛OutOfMemoryError异常。
本地方法栈:
它和虚拟机栈发挥的作用是非常类似的,只是它服务于虚拟机使用到的Native方法,而虚拟机栈则为虚拟机执行的java方法服务。