JVM的组成
我们先笼统的总结一下
- 类装载子系统
- 运行时的数据区(内存)
- 堆区(heap) : new 出来的对象都放到堆里
- 栈区(stack):线程栈,线程私有,存放线程用到 的局部变量,执行方法的时候,就会将用到的方法插入栈,一个方法对应于一个栈帧。
- 方法区(method area):存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。JDK 8开始,HotSpot将永久代(Permanent Generation)移除,取而代之的是元空间(Metaspace)。
- 程序计数器(PC): 指向当前指令指向的地址
- 字节码执行引擎
其实就这三部分,但是主要我们要了解它的流程
我画了一张图,大家可以看一下
第一步:
jdk将.java
文件编译为.class
字节码文件,
第二步:
字节码执行引擎将 A.class 文件放入JVM数据区,内存
此时我们需要了解一下JVM的内存模型:
JVM的数据区由五个部分组成
- 堆区(heap) : new 出来的对象都放到堆里
- 栈区(stack):线程栈,线程私有,存放线程用到 的局部变量,执行方法的时候,就会将用到的方法插入栈,一个方法对应于一个栈帧。
- 方法区(method area):存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。JDK 8开始,HotSpot将永久代(Permanent Generation)移除,取而代之的是元空间(Metaspace)。
- 程序计数器(PC): 指向当前指令指向的地址
我们主要讲一下 栈区:
**每个线程在执行时从栈区分配一块空间,每一个线程都会占据栈区的一处空间,所以又叫做线程栈,每个线程分配的空间叫做一个栈帧**
栈帧的组成部分:
- 局部变量表:
- 存储方法的局部变量,包括基本数据类型(如 int、float 等)、对象引用和返回地址等。
- 局部变量表的大小在编译时确定,根据方法中声明的变量数量分配空间。
- 方法调用时传递的参数也存储在局部变量表中。
- 操作数栈:
- 用于执行字节码指令时的操作数临时存储。
- 操作数栈的大小在编译时确定,栈帧的每条指令通过操作数栈进行计算和存储中间结果。
- 比如,进行加法操作时,两个操作数会从操作数栈中取出,结果会压回操作数栈中。
- 动态链接
- 用于支持方法调用时的符号引用到实际方法引用的解析(即连接到当前方法的常量池)。
- 每个栈帧包含一个指向常量池的引用,用于访问方法的相关符号信息和字段。
- 方法返回地址
- 保存了方法执行结束后的返回地址,用于返回到调用该方法的位置。
- 如果方法调用后需要返回给调用者,则返回地址会记录到栈帧中。
所以说,操作数中如果有引用数据类型,那么一定有变量指向堆区,每个栈也有一个指针指向方法区。
而函数真正的执行流程,大家可以去看操作系统(计算机组成原理) ,主要是通过PC(程序下一步执行的地址),来控制整个程序的执行,那么有一个问题,PC由谁控制呢?
是由我们JVM的第三个部分,JVM字节码执行引擎来决定的。
所以图上显示,字节码执行引擎控制 PC, 然后PC控制每一个线程栈的执行,进而控制整个程序。
标签:操作数,方法,线程,JVM,执行,哪几,栈帧,组成 From: https://blog.csdn.net/weixin_45691703/article/details/143488056