JVM_03 runtime data area 1_Stack_local variable table_Local Variables

2. Virtual machine stack

2.1 Overview
2.1.1 Background

Due to the cross-platform design, java instructions are designed according to the stack. Different platforms have different CPU architectures, so they cannot be designed as register-based.
The advantage is that it is cross-platform, the instruction set is small, and the compiler is easy to implement, but the disadvantage is that the performance is reduced, and more instructions are needed to achieve the same function.

2.1.2 Heap and stack in memory
  • The stack is the unit of runtime, and the heap is the unit of storage.
    That is: the stack solves the running problem of the program, that is, how the program is executed, or how to process the data. The heap solves the problem of data storage, that is, how and where to put the data.
  • Generally speaking, objects are mainly placed in the heap space, which is a relatively large part of the data area at runtime
  • The stack space stores local variables of basic data types and references to objects of reference data types
2.1.3 What is the virtual machine stack
  • Java Virtual Machine Stack (Java Virtual Machine Stack), also called Java stack in the early days.
    When each thread is created, a virtual machine stack is created, and a stack frame (Stack Frame) is stored inside, corresponding to this java method call again and again. It is thread private

  • The life cycle and thread are the same

  • Role: in charge of the operation of the java program, it saves the local variables of the method (8 basic data types, the reference address of the object), partial results, and participates in the call and return of the method.

    • Local variables: relative to member variables (or attributes)
    • Basic data variables: relative to reference type variables (classes, arrays, interfaces)
2.1.4 Features of the stack
  • The stack is a fast and effective way of allocating storage, the access speed is second only to the PC register (program counter)

  • There are only two operations directly on the Java stack by the JVM

    • Each method is executed, accompanied by pushing into the stack (push into the stack, push into the stack)
    • Stack work after execution
  • There is no garbage collection problem for the stack

2.1.5 Possible exceptions in the stack

The Java virtual machine specification allows the size of the Java stack to be dynamic or fixed

  • If a fixed-size Java virtual machine stack is used, the Java virtual machine stack capacity of each thread can be independently selected when the thread is created. If the stack capacity allocated by the thread request exceeds the maximum capacity allowed by the java virtual machine stack, the java virtual machine will throw a StackOverFlowError exception
/**
 * 演示栈中的异常
 */
public class StackErrorTest {
    public static void main(String[] args) {
        main(args);
    }
}
  • If the java virtual machine stack can be dynamically expanded, and cannot apply for enough memory when trying to expand, or there is not enough memory to create the corresponding virtual machine stack when creating a new thread, the java virtual machine will throw a OutOfMemoryError exception
2.1.6 Set the memory size of the stack

We can use the parameter -Xss option to set the maximum stack space of the thread. The size of the stack directly determines the maximum reachable depth of the function call.
(IDEA setting method: Run-EditConfigurations-VM options fill in the size of the specified stack-Xss256k)

/**
 * 演示栈中的异常
 *
 * 默认情况下:count 10818
 * 设置栈的大小: -Xss256k count 1872
 */
public class StackErrorTest {
    private static int count = 1;
    public static void main(String[] args) {
        System.out.println(count);
        count++;
        main(args);
    }
}
2.2 The storage structure and operating principle of the stack
2.2.1
  • Each thread has its own stack, and the data in the stack is in the format of a stack frame
  • Each method being executed on this thread corresponds to its own stack frame
  • The stack frame is a memory block and a data set that maintains various data information during the execution of the method
  • JVM has only two direct operations on the java stack, namely pushing and popping the stack frame, following the sum principle of first-in-last-out/last-in-first-out.
  • In an active thread, there will only be one active stack frame at a point in time. That is, only the stack frame (top stack frame) of the currently executing method is valid. This stack frame is called the current stack frame (Current Frame), and the method corresponding to the current stack frame is the current method (Current Frame)
  • All bytecode instructions run by the execution engine only operate on the current stack frame
  • If other methods are called in this method, the corresponding new stack frame will be created and placed at the top of the stack, becoming the new current stack frame.
  • The stack frames contained in different threads are not allowed to refer to each other, that is, it is impossible to refer to the stack frame of another thread in another stack frame
  • If the current method calls other methods, when the method returns, the current stack frame will return the execution result of this method to the previous stack frame, and then the virtual machine discards the current stack frame, making the previous stack frame the current stack frame again
  • There are two ways to return a function in a Java method, one is to return from a normal function, using the return instruction; the other is to throw an exception. No matter which method is used, it will cause the stack frame to be popped.
    Insert picture description here
/**
 * 栈帧
 */
public class StackFrameTest {
    public static void main(String[] args) {
        StackFrameTest test = new StackFrameTest();
        test.method1();
        //输出 method1()和method2()都作为当前栈帧出现了两次,method3()一次
//        method1()开始执行。。。
//        method2()开始执行。。。
//        method3()开始执行。。。
//        method3()执行结束。。。
//        method2()执行结束。。。
//        method1()执行结束。。。
    }

    public void method1(){
        System.out.println("method1()开始执行。。。");
        method2();
        System.out.println("method1()执行结束。。。");
    }

    public int method2(){
        System.out.println("method2()开始执行。。。");
        int i = 10;
        int m = (int) method3();
        System.out.println("method2()执行结束。。。");
        return i+m;
    }

    public double method3(){
        System.out.println("method3()开始执行。。。");
        double j = 20.0;
        System.out.println("method3()执行结束。。。");
        return j;
    }

}
2.2.2 The internal structure of the stack frame

Stored in each stack frame:

  • Local Variables Table (Local Variables)
  • Operand Stack (Operand Stack) (or expression stack)
  • Dynamic Linking (or implementation of runtime constant pool method reference)
  • Method return address (Return Adress) (or the definition of normal exit or abnormal exit of the method)
  • Some additional information

Insert picture description here

2.3 Local Variables Table (Local Variables)
2.3.1 Overview
  • Local variable table is also called local variable array or local variable table
  • Defined as a numeric array , mainly used to store method parameters and local variables defined in the method body. These data types include various basic data types, object references, and returnAddressleixing
  • Since the local variable table is built on the thread's stack, it is thread-private data, so there is no data security problem
  • The required capacity of the local variable table is determined during compilation and stored in the maximum local variables data item of the Code attribute of the method. The size of the local variable table will not be changed during the running of the method
  • The number of nested method calls is determined by the size of the stack. Generally speaking, the larger the stack, the more nested method calls. For a function, the more its parameters and local variables make the local variable table bloat, the larger its stack frame will be to meet the increased demand for the information passed by the method call. In turn, function calls will take up more stack space, resulting in fewer nested calls.
  • The variables in the local variable table are only valid in the current method call. When the method is executed, the virtual machine completes the transfer process of parameter values ​​to the parameter variable list by using the local variable table. When the method call ends, the local variable table will be destroyed with the destruction of the method stack frame.

Use the javap command to parse the bytecode file to view the local variable table, as shown in the figure:

Insert picture description here

Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here

操作数栈:
bipush -> 放在操作数栈中
istore -> 放在局部变量表中
如果是非static的话局部变量表开始为1 0为this
iload -> 局部变量表到Operand stack

byte i = 15;
int j = 8;
int k = i + j;

bipush 15
istore_1
bipush 8
istore_2
iload_1
iload_2
iadd
istore_3
reture
Slot变量槽,局部变量表在编译期就确定大小了。
局部变量表就是数组
slot:double和long为2个slot,int,float为1个slot

Insert picture description here

  • JVM will assign an access index to each slot in the local variable table, through this index you can successfully access the local variable value specified in the local variable table
  • When an instance method is called, its method parameters and local variables defined in the method body will be copied to each slot in the local variable table in order
  • If you need to access a 64-bit local variable value in the local variable table, you only need to sign an index. (For example: access long or double type variables)
  • If the current frame is created by the constructor or instance method, then the object reference this will be stored in the slot with index 0, and the remaining parameters are arranged in the order of the parameter table.
public class LocalVariablesTest {

    private int count = 1;
    //静态方法不能使用this
    public static void testStatic(){
        //编译错误,因为this变量不存在与当前方法的局部变量表中!!!
        System.out.println(this.count);
    }
}
Slot reuse

The slots in the local variable table in the stack frame can be reused. If a local variable exceeds its scope, the new local variable declared after its scope is likely to reuse the expired local variable Slots, so as to achieve the purpose of saving resources.

private void test2() {
        int a = 0;
        {
            int b = 0;
            b = a+1;
        }
        //变量c使用之前以及经销毁的变量b占据的slot位置
        int c = a+1;
    }

Guess you like

Origin blog.csdn.net/qq_43141726/article/details/114579985