Java 虚拟机在执行java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则依赖用户线程的启动和结束而建立和销毁。
Java虚拟机所管理的内存包括以下几个运行数据区域:程序计数器,虚拟机栈,本地方法栈,堆,方法区
(1)程序计数器:程序计数器是一块较小的内存区域,可以看作是当前线程所执行的字节码达行号指示器。由于java虚拟机的多线程是通过线程轮流切换并分配处理器的执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的计数器,各条线程之间计数器互不影响,独立存储(线程隔离的)。
(2)java虚拟机栈:线程隔离的,线程私有的,它的生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型:每个方法在执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中的入栈到出栈的过程。(虚拟机栈就是人们常说的栈内存)。
其中局部变量表存放了编译期可知的各种基本数据结构、对象引用。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是确定的,在方法运行期间不会改变这个大小。
在java虚拟机规范中,该区域会产生两种异常:StackOverFlowError 和 OutOfMemoryError.
(3)本地方法栈 :线程隔离的,其作用与java虚拟机栈作用类似,区别在于:虚拟机栈为虚拟机执行java 方法服务;而本地方法栈为虚拟机使用到的Native方法服务。该区域也会抛出:两种异常:StackOverFlowError 和 OutOfMemoryError
(4)java堆 :线程共享的,是java虚拟机所管理的内存中最大的一块。java堆是被线程共享的一块内存区域,在虚拟机启动时创建。其唯一目的就是存放对象实例,几乎所有的对象实例都在这分配内存。所有的对象实例以及数组都要在堆上分配内存。java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。
java堆是垃圾收集器管理的主要区域(所以也被称为GC堆),如果在堆中没有内存完成实例分配,并且堆也无法扩展时,会抛出OutOfMemoryError。
(5)方法区:线程共享的,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。当方法区无法满足内存分配需求时,会抛出OutOfMemoryError。运行时常量池是方法区的一部分。