专栏导航
JVM工作原理与实战
RabbitMQ入门指南
从零开始了解大数据
目录
专栏导航
前言
一、运行时数据区
二、Java虚拟机栈
1.栈帧的组成
2.局部变量表
3.操作数栈
4.帧数据
总结
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容。
Java虚拟机(JVM)在运行Java程序期间,会创建并维护一系列内存区域,这些区域总称为运行时数据区。这些区域根据其用途和特性,被严格定义并管理。《Java虚拟机规范》详细规定了这些区域的作用和行为,以确保所有Java虚拟机实现的一致性和正确性。
线程不共享区域:
线程共享区域:
Java虚拟机栈是Java技术中至关重要的部分,它负责管理方法调用中的基本数据。在执行Java程序时,Java虚拟机栈是线程私有的,即每个线程都拥有自己的Java虚拟机栈,并且随着线程的创建而创建,随着线程的销毁而回收。
Java虚拟机栈,运用栈式数据结构对方法调用过程中的基本数据进行管理。遵循先进后出(First In Last Out)的原则,每一个方法调用都会对应一个独立的栈帧(Stack Frame)进行数据存储。
Java虚拟机栈的核心组成部分是栈帧,每一个方法的调用都会对应一个栈帧。这个栈帧存储了该方法的所有信息,包括局部变量、操作数栈、动态链接、方法出口等。
局部变量表是存储在栈帧中的一块区域,它的作用是在方法执行过程中存放所有的局部变量。这些变量在编译成字节码文件时就可以确定其内容。
案例:
public class Demo1 { public static void test() { int i = 0; long j = 1; } }
字节码:
0 iconst_0 1 istore_0 2 lconst_1 3 lstore_1 4 return
局部变量表(Nr.表示编号;起始PC、长度表示生效范围):
案例分析图:
栈帧中的局部变量表是一个数组,数组中的每个位置称之为槽(slot)。每个槽可以存放一个值,long和double类型的数据会占用两个槽的空间,其他类型的数据则占用一个槽。
局部变量表(序号表示槽的起始编号):
在实例方法中,序号为0的位置专门用于存储当前调用方法的对象引用,即this指针。在运行时,该位置将存储实例对象的内存地址,以便于访问和操作对象的属性和方法。
案例:
public class Demo1 { public void test() { int i = 0; long j = 1; } }
局部变量表:
方法参数也会保存在局部变量表中,其顺序与方法中参数定义的顺序一致。
局部变量表保存的内容有:实例方法的this对象、方法的参数、方法体中声明的局部变量等。为了节省空间,局部变量表中的槽是可以复用的,一旦某个局部变量不再生效,当前槽就可以再次被使用。
案例:
public class Demo1 { public void test(int x,int y) { int i = 0; long j = 1; } }
局部变量表:
操作数栈是栈帧中虚拟机在执行指令过程中用来存放临时数据的一块区域。它是一种栈式的数据结构,如果一条指令将一个值压入操作数栈,则后面的指令可以弹出并使用该值。在编译期就可以确定操作数栈的最大深度,从而在执行时正确地分配内存大小。
案例:
public class Demo1 { public void test() { int i = 0; int j = i + 1; } }
字节码文件信息:
字节码:
0 iconst_0 1 istore_1 2 iload_1 3 iconst_1 4 iadd 5 istore_2 6 return
字节码分析:
0 iconst_0 将常量0放入操作数栈 1 istore_1 从操作数栈取出放入局部变量表1号位置 2 iload_1 将局部变量表1中的数据放入操作数栈 3 iconst_1 将常量1放入操作数栈 4 iadd 将操作数栈顶部的两个数据进行累加,结果放入栈中 5 istore_2 从操作数栈取出放入局部变量表2号位置 6 return 方法结束,返回
当当前类的字节码指令引用了其他类的属性或方法时,需要将符号引用(编号)转换成对应的运行时常量池中的内存地址。动态链接就保存了编号到运行时常量池的内存地址的映射关系。这样在执行时就可以快速地找到对应的内存地址。
方法出口指的是方法在正确或异常结束时,当前栈帧会被弹出,同时程序计数器应该指向上一个栈帧中的下一条指令的地址。所以在当前栈帧中,需要存储此方法出口的地址。这样在方法结束时,就可以快速地返回到上一个方法的执行位置。
异常表主要用于存储代码中异常的处理信息,它不仅涵盖了异常捕获的有效范围,还包含了try代码块和catch代码块执行后的字节码指令跳转位置。通过异常表,虚拟机能够精确地定位异常发生的位置,并采取适当的处理措施,从而确保程序的稳定性和可靠性。
案例:
public class Demo1 { public void test() { try { int i = 0; } catch (Exception e) { int j = 1; } finally { int k = 2; } } }
字节码文件信息:
字节码:
0 iconst_0 1 istore_1 2 iconst_2 3 istore_1 4 goto 21 (+17) 7 astore_1 8 iconst_1 9 istore_2 10 iconst_2 11 istore_1 12 goto 21 (+9) 15 astore_3 16 iconst_2 17 istore 4 19 aload_3 20 athrow 21 return
JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容,希望对大家有所帮助。