Java 虚拟机的内存模型,哪里说的最权威呢,当然是 Oracle 官网 啦!
本文从官网中截图,没有逐字翻译,
只是概括的总结,算是个人归纳。
Run-Time Data Areas
JAVA 虚拟机定义了数个 运行时数据区,供程序执行时使用。
其生命周期不尽相同,有的随线程的创建而创建,随线程的销毁而销毁。
有的则与虚拟机的生命周期相同。
1、HEAP (堆)
简要总结下:
- 堆内存是在虚拟机启动时创建,线程之间共享的内存。
- 堆内存的大小可以是固定的,也可以动态扩容或是缩容。
- 堆内存可被 GC 回收,堆内存溢出时,抛出 OutOfMemeryError。
- 堆内存可以是不连续的
2、Java Virtual Machine Stacks(虚拟机栈)
简要总结下:
- 线程创建时,会创建线程栈,为该线程所私有,
- 线程栈内存可以是不连续的,用以存储栈桢,
- 线程栈存局部变量、部分结果,有入栈出栈操作,
- 栈内存可设置初始大小,扩容的最大值,缩容的最小值
- 一个线程创建它的线程栈,大小超过其限制,抛出 StackOverflowError
- 栈扩容时空间不足,或是线程创建线程栈空间不足,抛出 OutOfMemoryError
3、 Method Area(方法区)
简要总结下:
- 所有线程共享方法区,
- 方法区存储类的结构,比如 运行时常量池,字段和方法的数据,构造函数和方法的代码,
- 可以设置方法区的大小,扩容的最大值,缩容的最小值。
4、The pc Register (程序计数器)
简要总结下:
- 线程私有
- 如果是native 方法,程序计数器可以认为是个摆设。
5、 Run-Time Constant Pool(运行时常量池)
简要总结下:
- 每个接口或类,运行期,在其 class 文件中 constant_pool 的指代,即是运行期常量池。
- 每个运行时常量池,都是在 方法区 中分配的。
- 当某个类或接口创建时,其 运行时常量池也会被创建
6、Native Method Stacks(本地方法栈)
这个没啥好说的,Java 底层有大量 native 方法,当线程运行 native 方法时,就在 native method stack 这块处理。
Frames (栈桢)
前面说过 Java Virtual Machine Stacks,这个就是存放栈桢的区域,
官文档中,把栈桢单独列出来说明了。
简要总结下:
- 栈桢 是用来存放局部变量的,也可以用来执行动态链接,可以返回方法的执行结果,也可以抛出方法的异常。
- 线程创建栈桢,分配在 Java Virtual Machine stack 区,每个栈桢有自己的局部变量数组,操作数栈,及 当前方法的运行时常量池的引用。
- 当一个线程创建了一个栈桢,这个栈桢只属于该线程,其它线程无法获得该栈桢的引用。
1、Local Variables(局部变量)
简要总结下:
- 局部变量数组,通过下标定位,下标从0开始,不能越界
- boolean, byte, char, short, int,float, reference 类型的值,占用一个局部变量,long 和 double 类型却需要两个。
- 当一个实例方法被调用时,第0个局部变量通常是当前对象的引用,即 JAVA 语言中的 this
2、Operand Stacks(操作数栈)
简要总结下:
- 操作数栈,先进后出
- 操作数栈,通常情况下指的是当前栈桢的操作数栈
- 方法的传参、返回结果,都会存到操作数栈中
3、Dynamic Linking(动态链接)
简要总结下:
- 每个栈桢里,包含了当前方法的运行时常量池的引用,以此来支持动态链接的实现
- 一个方法的class文件代码,通过符号引用,可指向被调用的方法及参数
- 动态链接可以把方法的符号引用,解析为直接引用,解析变量在内存中的偏移量等
如果想深入了解,可 点击 这里