JVM内存分区
内存分区和内存模型是两个概念
操作系统内存分区
- 栈(Stack)
- 堆(Heap)
- 未初始化数据段(BSS)
- 数据段(Data Segment)
- 文本段(Literal Segment)
- 代码段(Code Segment)
JVM内存分区
- 程序计数器(PC)
- 虚拟机栈(JVM Stack)
- 本地方法栈(Native Method Stack)
- 堆(Heap)
- 方法区(Method Area)
橙色虚线包裹的就是线程共享的,被红色实现包裹的是线程隔离的
程序计数器
在硬件层面,程序计数器是寄存器,是用来存储指令地址给处理器执行,
在JVM中,它的作用就是用来存储字节码指令的地址,提供给执行引擎去执行
这里我们从侧面去查看该特新
1 | public class Demo { |
然后先编译javac Demo.java
反编译javap -l -c Demo.class
得到以下字节码
1 | Compiled from "Demo.java" |
虚拟机栈
也叫java方法栈,java方法的调用对应着栈帧的入栈与出栈。
3个重点:
- 栈帧
- 栈帧出现时机
- 栈帧的构成
栈帧
栈帧主要有四部分组成:局部变量表、操作数栈、动态连接、返回地址
- 局部变量表
- 主要存储方法的参数、定义在方法内的局部变量,包括基本数据类型(8大)对象的引用地址,返回值地址。
- 局部变量表中存储的基本单元为变量槽(Slot),32位(4字节)以内的数据类型占一个slot,64位(long,double)的占两个slot。
- 局部变量表是一个数字数组,byte、short、char都会被转化为int,boolean类型也会被转化为int,O代表false、非0代表true。局部变量表的大小是在编译期间决定下来的,所以在运行时它的大小是不会变的。
- 局部变量表中含有直接或者间接指向的引用类型变量时,不会被垃圾回收处理。
- 操作数栈
就是用来存储操作数的栈,这里的操作数大部分就是方法内的变量
作用:
- 存储操作数
- 操作数栈可以方便指令顺序读取操作数
指令 | 含义 |
---|---|
iload | int型变量入栈 |
istore | 栈顶数值存入局部变量 |
iadd | 弹出栈顶两个操作数,并将求和的int值压入栈中 |
- 动态连接
java中的多态就是通过动态连接实现的
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用都是为了支持方法调用过程中的动态连接
连接是将部分符号引用替换为直接引用,对于有些方法,JVM并不能判断它们的具体实现,只有在真正运行的时候,才可以根据实际类型进行连接,这就是动态连接
本地方法栈
本地方法是由非java语言实现的函数,一般是一些和操作系统底层相关的函数