Stack frame is a data structure that supports the method invocation and method execution of a virtual machine, which is the stack element of the virtual machine stack of the data area when the VM is running. The stack frame stores information such as the local variable table of the method, the operand stack, the dynamic connection, and the method return address. The first method, from the start of the call to the completion of execution, corresponds to the process of a stack frame from the stack to the stack in the virtual machine stack.
Each stack frame includes a local variable table, a stack of operands, a dynamic connection, a method return address, and some additional additional information. When compiling the code, how much local variable tables are needed in the stack frame, how deep the operand stacks are, and written to the Code property of the method table, so how much memory is allocated to a stack frame and not affected by the program runtime variable data, but only by the implementation of the specific virtual machine.
A method call chain in a thread can be long, and many methods handle the execution state at the same time. For the execution engine, in the active thread, only the stack frame at the top of the virtual machine stack is valid, called the current stack frame, and the method associated with the stack frame is called the current method. All bytecode directives run by the execution reference are operated on the current stack frame only. The conceptual structure of the stack frame is as follows:
1. Local Variables Table
A local variable table is a set of variable value storage spaces that are used to store method parameters and local variables defined inside the method. When a Java program compiles to a class file, it determines the capacity of the maximum local variable table that the method needs to allocate in the Max_locals data item of the Code property of the method table.
When the method executes, the virtual machine uses the local variable table to complete the parameter list, and if it is an instance method, the slot for each 0-bit index in the local variable table defaults to the reference used to pass the object instance to which the method belongs, and the implied argument can be accessed through the keyword "This" in the method. The remaining parameters are arranged in the order of the parameter list, occupying a local variable slot starting at 1, and assigning the remaining slots based on the order and scope of the variables defined within the method body, after the parameter table has been allocated. A slot in a local variable table is reusable, a variable defined in the method body, whose scope does not necessarily override the entire method, and if the value of the current bytecode PC calculator exceeds the scope of a variable, the slot corresponding to that variable can be used by other variables.
Local variables do not have a "prep phase" as the class variable described earlier. The class variable has a two-time assignment of the initial value, one at the preparatory stage, and the other at the initialization stage, giving the programmer a defined value. So even when the programmer does not assign a value to a class variable during the initialization phase, the class variable still has a definite initial value. But local variables are different, if a local variable is defined but not assigned the initial value is not available.
2. Operand stacks
The operand stack is also often referred to as the Operation Stack, which is a post-in-first-out stack. As with local variable tables, the maximum depth of the operand stack is also written to the Max_stacks data item of the Code property of the method table when compiling. Each element of the operand stack can be any Java data type, including a long and a double. The 32-bit data type occupies a stack capacity of 1, and the 64-bit data type occupies a stack capacity of 2. Stack capacity is the "word width", for 32-bit virtual machines, a "word width" accounted for 4 bytes, for 64-bit virtual machine, a "word width" accounted for 8 bytes.
When a method has just executed, the operand stack of this method is empty, in the process of the method execution, there will be various bytecode to the operand stack to write and extract values, that is, into the stack and the stack operation. For example, when doing arithmetic, it is done by the operand stack, or by invoking other methods by the operand stack to pass the arguments.
In addition, in the conceptual model, two stack frames as the elements of the virtual machine stack, are completely independent of each other, but most of the implementation of the virtual machine will do some optimization processing, so that the two stack frames appear to overlap a part. The partial operand stack of the next stack frame overlaps with the partial local variable table of the stack frame above, so that a portion of the data can be shared when the method call is returned, without the need for additional parameter copy passing, such as:
3. Dynamic Connection
Each stack frame contains a reference to the owning method of the stack frame in the run-time pool, which is held to support dynamic connections during method invocation. There are a number of symbolic references in the constant pool of class files, and the method invocation directives in the bytecode are referenced as parameters to the symbol in the constant pool that points to the method. Some of these symbolic references are converted to direct references during the class load phase or the first use, which is called static parsing. The other part will be converted to a direct reference during each run, which is called dynamic connectivity.
4. Method return Address
When a method is executed, there are two ways to exit this method. The first is that the execution engine encounters a bytecode instruction returned by either method, at which point the return value may be passed to the method caller of the upper layer (the method calling the current method is called the caller), and whether the type of the return value and the return value will be determined based on the method return instruction encountered. This exit method is called normal completion exit (normal method invocation completion).
Another way to exit is to encounter an exception during the execution of the method, and the exception is not handled in the method body, whether it is an exception generated inside the Java virtual machine, or an exception that is generated in code using the Athrow bytecode directive, as long as no matching exception handler is found in the exception table of this method. Will cause the method to exit, which is called an abnormal completion exit (abrupt method invocation completion). A method exits with an exception completion exit, and the call to it does not produce any return value.
Regardless of the way you exit, before the method exits, you need to return to the location where the method was called before the program can continue, and the method returns may need to hold some information in the stack frame to help restore the execution state of its upper method. In general, when the method exits normally, the value of the caller's PC counter can be used as the return address, and the counter value is likely to be saved in the stack frame. When the method exits unexpectedly, the return address is determined by the exception handler, which is not normally saved in the stack frame.
The process of exiting the method is actually the same as putting the current stack frame out of the stack, so the actions you can take when exiting are: Restoring the local variable table of the upper method and the operand stack, and pressing the return value (if any) into the stack of stacks that call the stack frame, calling the value of the PC counter to point to an instruction following the method
5. Additional Information
The virtual machine specification allows specific virtual machine implementations to add information that is not described in the specification to the stack frame, such as highly relevant information, which is entirely dependent on the specific virtual machine implementation. In the actual development, the dynamic connection, the method return address and other additional information is generally classified as a class, called the stack frame information.
In-depth understanding of Java Virtual Machine notes---runtime stack frame structure