java虚拟机在执行java程序的过程中会把它管理的内存分为若干个不同的数据区域
- 程序计数器
- java虚拟机栈
- 本地方法栈
- Java堆
- 方法区
- 运行时常量池
- 直接内存
程序计数器
程序计数器(program counter register)是一块较小的内存空间,它可以看作是当前线程执行的字节码行号指示器。工作原理就是通过改变这个计数器的值来选择当前线程的下一条需要执行的字节码指令,如分支,循环,跳转,异常,线程恢复等基础功能都需要来依赖程序计数器。无OOM异常
java虚拟机栈
与计数器一样,栈也是线程素有的,它的生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型:每个方法执行的同时都会创建一个栈桢,栈桢用来存储局部变量表,操作数栈,动态链接,方法出口等信息。
局部变量表存放了编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double),对象引用(不是对象本身,可能是对象引用指针)和returnAddress类型,也就是方法出口信息。
double和lang占用2哥slot局部变量表的空间,其余的数据类型占据1个,局部变量表所需要的内存空间在编译期间完成。在方法执行期间不会改变局部变量表的大小。
会出现OOM
本地方法栈
本地方法栈为虚拟机使用到的native方法服务。会出现StackOverflowError和OOM
java堆
java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
方法区
方法区和Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机家在的类信息,常量,静态变量,即时编译器编译后的代码等数据,java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它又个别名叫做Non-Heap(非堆)。
运行时常量池
运行时常量池是方法区的一部分,Class文件中除了有类的版本,方法,字段,接口等描述信息外,还有一项信息就是常量池,用于存放编译期生成的各种字面变量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
直接内存
并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,但是也会产生OOM,堆外内存,受物理机内存大小的限制。