正确理解JVM中的栈帧数据结构

44 阅读2分钟

JVM中的栈帧数据结构有哪些

看到有些博客和书中总结的栈帧数据结构:

错误认识:

每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存,每个栈帧中存储着:

局部变量表:存储方法里的 Java 基本数据类型以及对象的引用

动态链接:也叫指向运行时常量池的方法引用

方法返回地址:方法正常退出或者异常退出的定义

操作数栈或表达式栈和其他一些附加信息

这种说法不能说完全错误,但是和JVM规范有些许出入。

根据JVM规范,方法区的数据结构包含局部变量表、操作数栈、指向运行时常量池的索引和额外信息。

动态连接不是数据结构,而是一个过程,即把符号引用翻译成内存地址的过程。

方法返回地址属于JVM规定的一种数据类型,其属于局部变量表。

虚拟机规范如下:

A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.

A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception). Frames are allocated from the Java Virtual Machine stack (§2.5.2) of the thread creating the frame. Each frame has its own array of local variables (§2.6.1), its own operand stack (§2.6.2), and a reference to the run-time constant pool (§2.5.5) of the class of the current method.

A frame may be extended with additional implementation-specific information, such as debugging information.

Each frame (§2.6) contains a reference to the run-time constant pool (§2.5.5) for the type of the current method to support dynamic linking of the method code. The class file code for a method refers to methods to be invoked and variables to be accessed via symbolic references. Dynamic linking translates these symbolic method references into concrete method references, loading classes as necessary to resolve as-yet-undefined symbols, and translates variable accesses into appropriate offsets in storage structures associated with the run-time location of these variables.

This late binding of the methods and variables makes changes in other classes that a method uses less likely to break this code.

简单翻译一下:

栈帧用来存储数据和部分结果,同时执行动态链接,返回方法返回值或者分派异常。

方法调用时创建栈帧。方法结束时(包括正常返回和异常结束)栈帧销毁。虚拟机栈负责栈帧的创建。每个栈帧拥有局部变量表、操作数栈和指向当前类中方法的运行时常量池。栈帧可以选择添加额外实现信息,比如debug 信息。

动态连接将符号解析为直接引用,按需加载未解析的符号引用,将对变量的访问解析成内存的具体位置。

对方法和变量的延迟加载使得其他类中变化对当前代码的影响更小,不易出错。