《深入Java虚拟机》导读之四: JVM体系结构

时间:2022-12-23 16:02:16

如下图所示jvm的结构:

《深入Java虚拟机》导读之四: JVM体系结构
运行时数据区: 当程序运行时, 它需要内存来存放字节码以及从class文件中提取出来的信息, 如: 实例化的对象, 方法参数, 返回值, 局部变量, 运算中间值等等.jvm把它们组织, 存放在运行时数据区.

方法区: 存放jvm加载的类型信息.包括: 类型基本信息, 常量池, 字段信息, 方法信息, 类变量, 指向ClassLoader的引用, Class类的引用, 方法表.

类型信息:对每个jvm加载的类型, 它需要存储这些信息在方法区: 类型全限名, 直接superclass全限名, 是否是类或接口, 类型修饰符, 直接的接口列表.

常量池:包括直接字面常量如字符串, 整数, 浮点数的常量, 类型, 字段, 方法的符号引用.每个常量都有一个索引.

字段信息: 包括字段名, 类型, 修饰符.

方法信息: 方法名, 方法返回值, 参数类型和数量, 方法修饰符, 方法的字节码, 操作数栈的长度, 栈帧的局部数据区长度, Exception表.

静态变量(类变量): 即被所有的类实例共享的变量;

java堆: 程序中创建的类的实例和数组, 包括class对象和exception对象,存放在堆里面. 虚拟机中所有的线程共享堆空间, 堆中除了存储对象的实例数据外,还要存储该对象的引用和指向方法去中类型信息的指针. 如下图展示了堆中数据的组织以及和方法区的联系:

《深入Java虚拟机》导读之四: JVM体系结构

下图展示了数组的一种组织方式:

《深入Java虚拟机》导读之四: JVM体系结构

java栈: 当一个新线程启动的时候, jvm为它创建并维护单独的栈, 一个线程不能touch另一个线程的栈. 栈由栈帧组成, 当一个线程调用一个方法的时候, jvm创建一个新栈帧并把它压入当前线程的栈, 这个栈被称为当前栈, 这个正在被调用的方法称为当前方法, 它里面包含参数, 局部变量, 运算的中间值等等. 一个方法有两种结束方式, 一种是正常的返回, 另一种是抛出Exception, 无论那种方式, jvm都会弹出栈顶并丢弃该栈帧, 那么前一个方法的栈帧会称为当前栈帧. 如下图展示了3个有线程的程序的栈:

《深入Java虚拟机》导读之四: JVM体系结构

程序计数器: 每个线程拥有自己的程序计数器, 它指向下一条指令. 当线程调用本地方法的时候, 它为undefined.

本地方法栈:当一个线程调用了一个本地方法, 则会跳入一个本地方法栈. 本地方法返回后可能再次跳回java方法栈. 如图:

《深入Java虚拟机》导读之四: JVM体系结构

执行引擎:在Java虚拟机规范中,执行引擎的行为使用指令集来定义. 运行中Java程序的每一个线程都是一个独立虚拟机执行引擎的实例,从线程生命周期的开始到结束,它要么在执行字节码,要么在执行本地方法。Java虚拟机的实现可能用一些对用户程序不可见的线程,比如垃圾收集器,这样的线程不需要实现的执行引擎实例,所有属于用户运行程序的线程,都是在实际工作的执行引擎.

指令集 方法的字节码流是由Java虚拟机的指令序列构成的,每一条指令包含一个单字节的操作码,后面跟随0个或多个操作数。操作码表明需要执行的操作;操作数向Java虚拟机提供执行操作码需要的额外信息。操作码本身就已经规定了它是否需要跟随操作数,以及如果有操作数的话,它是什么形式的。很多Java虚拟机的指令不包含操作数,仅仅是由一个操作码字节构成的.