编程知识 cdmana.com

Java JVM -- 5. Java virtual machine stack

Virtual machine stack Overview

   Because of the cross platform design ,Java The instructions of are designed according to the stack . Different platforms CPU Different architectures , So it can't be designed as register based .  Stack implementation The advantage is cross platform , Instruction set is small , The compiler is easy to implement , The disadvantage is that the performance is reduced , More instructions are needed to implement the same function .

   Quite a few Java When developers mention Java Memory structure , Will be very rough to JVM The memory area in is understood as only Java Pile up (heap) and Java Stack (stack), This division is directly inherited from the traditional C、C++ Program memory layout structure , stay Java The language is a little rough , The actual partition of memory area is more complicated than this .

First of all, we need to be clear about :

   A stack is a unit of runtime , And the heap is the unit of storage .

    * The stack solves the running problem of the program , That is, how the program is executed , Or how to deal with the data .

    * Heap solves the problem of data storage , How to put the data , Where will it be? .

Java What is the virtual machine stack

  Java Virtual machine stack (Java Virtual Machine Stack), The early days were also called Java Stack . Each thread creates a virtual machine stack when it is created , It stores stack frames one by one (Stack Frame), Corresponding again and again Java Method call .

   Stack frame (Stack Frame) Used to store local variables 、 The stack of operands 、 Dynamic connection 、 Method returns address and other information . Each method is called until the end of the execution process corresponds to a stack frame in the virtual machine stack from the stack to the stack process .

Life cycle

   Same as the program counter Java Virtual machine stack (Java Virtual Machine Stack) It's also thread private , It has the same life cycle as a thread .

effect

   executive director Java Program operation , It holds the local variables of the method 、 Part of the result , And participate in the method call and return .

local variable , It's compared to member variables ( Or attributes ).

Basic data type variable VS Reference type variable ( class 、 Array 、 Interface ).

The characteristics of the stack

   Stack is a fast and efficient way to allocate storage , Access speed is second only to the program counter .JVM Direct pair Java There are only two operations on the stack :

    ①  Each method executes , Along with the stack ( Push 、 Pressing stack ).
    ②  After the execution of the stack work .

   There is no garbage collection problem for the stack ( Stack overflow exists ).

  Virtual machine stack

About stack exceptions

  Java The virtual machine specification allows Java Stack size is dynamic or fixed .

   If you use a fixed size Java Virtual machine stack , And every thread Java The virtual machine stack capacity can be selected independently when the thread is created . If the stack capacity allocated by the thread request exceeds Java Maximum capacity allowed by virtual machine stack ,Java The virtual machine will throw a StackOverflowError abnormal ( Stack overflow ).

   If Java The virtual machine stack can be expanded dynamically , And can't get enough memory when trying to expand , Or when creating a new thread, there is not enough memory to create the corresponding virtual machine stack , that Java The virtual machine will throw a outOfMemoryError abnormal ( out of memory ).

We can test it :

public class StackErrorTest {
    private static int count = 1;
    public static void main(String[] args) {
        System.out.println(count++);
        main(args);
    }
}

Running results :

   When the stack depth reaches 15419 When , There is insufficient stack memory space .

Set stack memory size  

   We can use parameters -Xss Option to set the maximum stack space for the thread , The size of stack directly determines the maximum depth of function call .

Example :

   Set the stack size to 1MB:-Xss1m.

   Set the stack size to 1KB:-Xss1k.

Eclise in , Set the stack memory size for the current class :

   Right click in the code area --> Run As -- >RunConfigurations --> On the left, select the class you want to set --> Right click Arguments Options --> VM arguments Parameter setting --> then Apply --> Run.

   Scope : It only works for this project .

Eclipse in , Set stack memory size globally :

   menu bar Window --> preference --> Java --> Installed JREs --> Select the currently used package --> Edit --> Default VM Arguments Parameter setting --> Finish.

   Scope : It works for all projects .

The storage unit of a stack

   Each thread has its own stack , The data in the stack is in stack frame (Stack Frame) The format of exists .

   Each method executing on a thread corresponds to a stack frame (Stack Frame).

   Stack frame is a memory block , Is a dataset , It maintains all kinds of data information in the process of method execution .

What is stored in the stack ?

   Each thread has its own stack , The data in the stack is in stack frame (Stack Frame) The format of exists . Each method being executed on this thread corresponds to a stack frame (Stack Frame). Stack frame is a memory block , Is a dataset , It maintains all kinds of data information in the process of method execution .

  JVM Direct pair Java There are only two operations on the stack , It's the stack pressing and stack out of the stack frame , follow “ First in, then out ”/“ Last in, first out ” principle .

   In an active thread , At one point in time , There will only be one active stack frame . That is, only the stack frame of the currently executing method ( Stack top stack frame ) It works , This stack frame is called the current stack frame (Current Frame), The method corresponding to the current stack frame is the current method (Current Method), The class that defines this method is the current class (Current Class).

   All bytecode instructions run by the execution engine operate only on the current stack frame .

   If you call other methods in this method, , The corresponding new stack frame will be created , At the top of the stack , Become the new current frame .

How stack works

   Stack frames contained in different threads are not allowed to refer to each other , That is, it is impossible to reference the stack frame of another thread in one stack frame .

   If the current method calls another method , Method return , The current stack frame will return the execution result of this method to the previous stack frame , next , The virtual opportunity discards the current stack frame , Make the previous stack frame become the current stack frame again .

  Java Method has two ways to return a function , One is a normal function return , Use return Instructions ; The other is to throw an exception . Either way , Will cause the stack frame to pop up .

The memory structure of the stack

Each stack frame stores :

   Local variable table (Local Variables)

   The stack of operands (operand Stack)( Or expression stack )

   Dynamic links (DynamicLinking)( Or a method reference to the runtime constant pool )

   Method return address (Return Address)( Or method normal exit or abnormal exit definition )

   Some additional information

   The stack under each thread is private , So each thread has its own stack , And there are many stack frames in each stack , The size of stack frame is mainly determined by the local variable table and The stack of operands determines .

Local variable table

   Local variable table (Local Variables), It's called an array of local variables or a table of local variables .

   Defined as an array of numbers , It is mainly used to store method parameters and local variables defined in the method body. These data types include various basic data types 、 Object reference (reference), as well as returnAddress type .

   Because the local variable table is built on the thread stack , It's the thread's private data , So there is no data security problem .

   The size of the local variable table is determined at compile time , And stored in the Code Attribute maximum local variables In data item . The size of the local variable table does not change during the method run .

   The number of nested method calls is determined by the number of nested method calls . Generally speaking , The bigger the stack is , The more nested method calls . For a function , The more parameters and local variables it has , Make the local variable table expand , The bigger the stack frame is , Call the method to meet the needs of information transfer . Then function calls will take up more stack space , As a result, the number of nested calls will be reduced .

   Variables in the local variable table are only valid in the current method call . When the method executes , Virtual machine completes the transfer process from parameter value to parameter variable list by using local variable table . When the method call ends , With the destruction of method stack frames , The local variable table will also be destroyed .

Variable slot (Slot)

   Parameter values are always stored in the local variable array index 0 Start , To array length -1 End of index of .

   The most basic storage unit of a local variable table is Slot( Variable slot ), The local variable table stores various basic data types known at compile time (8 Kind of ), Reference type (reference),returnAddress Variable of type .

   In the local variable table ,32 Types within bits occupy only one slot( Include returnAddress type ),64 Bit type (long and double) Take two slot.

  byte、short、char Converted to before storage int,boolean Also converted to int,0 Express false, Not 0 Express true.long and double They occupy two slot.

  JVM For each of the local variable tables Slot All assigned an access index , Through this index, the local variable values specified in the local variable table can be accessed successfully , When an instance method is called , Its method parameters and local variables defined in the method body will be copied to each of the local variable tables in order slot On , If you need to access one of the local variables table 64 bit When the local variable value of , Just use the previous index ( such as : visit long or double Type variable ).

Local variable table of common methods

   If the current frame is created by a constructor or instance method , Then the object references this Will be stored in index by 0 Of Slot It's about , The rest of the parameters continue to be arranged in parameter table order .

( A method of construction or ) Local variable table of instance method

Reuse of variable slot

   The slots in the local variable table in the stack frame can be reused , If a local variable goes beyond its scope , The new local variable declared after its scope is likely to reuse the slot of the expired local variable , So as to save resources .

The comparison between static variables and local variables

Classification of variables :

*  By data type : Basic data type 、 Reference data type .

* According to the position declared in the class : Member variables ( Class variables , Instance variables )、 local variable .

* Class variables :linking Of paper Stage , Assign default values to class variables ,init Stage to assign values to class variables , Static code blocks .

* Instance variables : As objects are created , The instance variable space is allocated in the heap space , And default assignment .

* local variable : An explicit assignment must be made before use , Otherwise, the compilation fails .

   After the parameter list is assigned , According to the order and scope of the variables defined in the method body .

   We know that class variable table has two initialization opportunities , For the first time “ Preparation stage ”, Perform system initialization , Set a zero value on a class variable , The other was in “ initialization ” Stage , Give the programmer the initial value defined in the code .

   Unlike class variable initialization , There is no system initialization process in the local variable table , This means that once a local variable is defined, it must be artificially initialized , Otherwise it won't work .

   In the stack frame , The most relevant part of performance tuning is the local variable table mentioned earlier . When the method executes , The virtual machine uses the local variable table to complete the method transfer .

   Variables in the local variable table are also important garbage collection root nodes , As long as the objects directly or indirectly referenced in the local variable table are not recycled .

The stack of operands

   The stack of operands (Operand Stack), Each independent stack frame contains a list of local variables , One in and one out (Last-In-First-Out) Of The stack of operands , It can also be called Expression stack (Expression Stack).

summary

   The stack of operands , During method execution , According to bytecode instruction , Write or extract data from the stack , That's the stack (push) and Out of the stack (pop).

   Some bytecode instructions push values into the operands stack , The rest of the bytecode instructions take the operands out of the stack , Use them and push the results on the stack . such as : Perform replication 、 In exchange for 、 Sum and so on .

Summation instruction

The code for :

   The stack of operands , It is mainly used to save the intermediate results of the calculation process , At the same time, it serves as the temporary storage space for variables in the calculation process .

   The stack of operands is JVM A workspace of the execution engine , When a method is first executed , A new stack frame will also be created , The operand stack of this method is empty . Be careful : At this time, the array has a length , Because once an array is created , So it's immutable .

   Each stack of operands has a clear stack depth for storing values , The maximum depth required is defined at compile time , Save in the method of Code Property named maxstack Of .

   Any element in the stack can be arbitrary Java data type :

     32bit The type occupies a stack unit depth .

     64bit The type of the stack occupies two stack units of depth .

   The operand stack does not use the way of access index to access data , But only through the standard stack and stack operations to complete a data access . If the called method has a return value , Its return value will be pushed into the stack of operands in the current stack frame , And update the PC The next bytecode instruction to be executed in the register .

   The data type of the elements in the operand stack must strictly match the sequence of bytecode instructions , This is verified by the compiler during the compiler , At the same time, in the class loading process, the data flow analysis phase of the class verification phase needs to be verified again .

   in addition , We said Java The interpretation engine of virtual machine is stack based execution engine , The stack refers to the operand stack .

Code tracking

Let's write a piece of code first :

public void testAddOperation() {
    byte i = 15;
    int j = 8;
    int k = i + j;
}

Use javap command (javap -v Class name .class) Decompile class file :

byte、short、char、boolean It's all used inside int For preservation .

From the above code, we can know , We all passed bipush For operands 15 and 8 Do stack operation

At the same time iadd Method to add ,i It stands for int, That is to say int Type of addition operation

The execution process is as follows :

   First execute the first statement ,PC Register points to 0, That is, the instruction address is 0, And then use bipush Let the operands 15 Push .

   After the execution , Give Way PC + 1, Point to the next line of code , The next line of code is to store the variables in the table 1 The location of , We can see that an element has been added to the list of local variables :

Why is the local variable table not from 0 The beginning ?

   In fact, the local variable table also comes from 0 At the beginning , But because 0 The number number of the store is this The pointer , So we just omit .

   then PC+1, It points to the next line . Let the operands 8 Also in the stack , At the same time store operation , In the local variable table :

   And then from the local variable table , Put the data on the stack of operands in turn :

   Then add the two elements in the stack of operands , And stored in the local variable table 3 The location of :

   Last PC The location of the register points to 10, That is to say return Method , Then exit the method directly .

Stack top caching technology

Stack top caching technology :Top Of Stack Cashing.

   I mentioned it earlier , Virtual machines based on trestle architecture use more compact zero address instructions , But when completing an operation, it is necessary to use more stack in and out instructions , This also means that more instruction dispatch will be required (instruction dispatch) Times and memory reads / Write times .

   Because the operands are stored in memory , Therefore, memory reads are performed frequently / Write operations will inevitably affect the speed of execution . To solve this problem ,HotSpot JVM The designers of the stack top cache (Tos,Top-of-Stack Cashing) technology , Cache all stack top elements in physical CPU In the register of , In order to reduce the memory read / Write times , Improve the execution efficiency of the execution engine .

Based on register architecture : Fewer instructions , Fast execution .

Dynamic links

Dynamic links 、 Method return address 、 Additional information : These areas are called frame data areas in some places .

   Dynamic links :Dynamic Linking. Each stack frame contains a point to Runtime constant pool Reference to the method to which the stack frame belongs , The purpose of including this reference is to support the dynamic linking of the code of the current method (Dynamic Linking). such as :invokedynamic Instructions .

   stay Java When the source file is compiled into a bytecode file , All variable and method references are referred to as symbols (symbolic Reference) Save in class In the constant pool of files .

   such as : Describes when a method calls another method , It is represented by a symbolic reference to a method in the constant pool , The purpose of dynamic linking is to convert these symbolic references into direct references of calling methods .

Why a runtime constant pool is needed ?

   Because in different ways , Can call the same constant or method , So just store one copy , Save a space . The function of constant pool is to provide some symbols and constants , It is easy to identify the instruction .

Method call : Analysis and distribution

   stay JVM in , Converting a symbolic reference to a direct reference to a calling method is related to the binding mechanism of the method .

link

Static links

   When a bytecode file is loaded into JVM Internal time , If the target method to be called is known at compile time , And the operation period remains unchanged , In this case, the process of converting symbolic references of calling methods to direct references is called static linking .

Dynamic links

   If the called method cannot be determined at compile time , in other words , You can only convert the symbol of the called method to a direct reference during program runtime , Because of the dynamic nature of this reference conversion process , So it's also called dynamic linking .

Binding mechanism

   The binding mechanism of the method corresponding to the link is : Early binding (Early Binding) And late binding (Late Binding). Binding is a field 、 Methods or classes are replaced by direct references in symbolic references , It only happened once .

Early binding

   If the target method is called in the early compilation period , And the operation period remains unchanged , You can bind this method to the type it belongs to , thus , Because it is clear which target method is called , Therefore, you can use static links to convert symbol references to direct references .

Late binding

   If the called method cannot be determined at compile time , You can only bind related methods according to the actual type during the program run time , This binding is also called late binding .

Virtual method and non virtual method

   If the method determines the specific calling version at compile time , This version is immutable at run time , Such a method is called non virtual method .

   Static methods 、 Private method 、fina1 Method 、 Instance builder 、 Parent methods are non virtual methods .

   Other methods are called virtual methods .

The premise of using polymorphism of subclass object :

  • Class inheritance

  • Method rewrite

The following method call instructions are provided in the virtual machine :

Normal call instructions :

    • invokestatic: Call static methods , The parsing phase determines the unique method version .

    • invokespecial: call <init> Method 、 Private and superclass methods , The parsing phase determines the unique method version .

    • invokevirtual: Call all virtual methods .

    • invokeinterface: Call interface method .

Call instructions dynamically :

    • invokedynamic: Dynamically resolve the method to be called , And then execute

   The first four instructions are fixed in the virtual machine , The call and execution of the method cannot be interfered by human beings , and invokedynamic The instruction supports the user to determine the method version . among invokestatic Instructions and invokespecial A method called by an instruction is called a non virtual method , The rest (fina1 Except decorated ) It's called virtual method .

invokednamic Instructions

  JVM Bytecode instruction set has been relatively stable , Until Java7 It's just added a new one invokedynamic Instructions , This is a Java In order to achieve 『 Dynamic type language 』 An improvement made with support .

   But in Java7 Direct generation is not provided in invokedynamic Method of instruction , Need help ASM This underlying bytecode tool to generate invokedynamic Instructions . until Java8 Of Lambda Occurrence of expression ,invokedynamic Generation of instructions , stay Java There is a direct way to generate .

  Java7 The essence of the dynamic language type support added in is to Java Modification of virtual machine specification , Not right. Java Modification of language rules , This one is relatively complicated , Added method call in virtual machine , The most direct beneficiary is running in Java Compiler for dynamic language of platform .

Dynamically typed languages and statically typed languages

   The difference between dynamically typed languages and statically typed languages is : Check the type at compile time or run time , Satisfying the former is a statically typed language , Instead, it's a dynamically typed language .

   To put it bluntly, it is , Static type language is to judge the type information of variable itself ; Dynamic type language is to judge the type information of variable value , Variables have no type information , Only variable values have type information , This is an important feature of dynamic language .

Java:String info = "mogu blog"; (Java It's statically typed , It compiles and checks the type first )

JS:var name = "shkstart"; var name = 10; (JS It's dynamic language , Check at runtime )

The nature of method rewriting

Java The essence of method rewriting in language :

   Find the actual type of object executed by the first element at the top of the stack of operands , Write it down as C.

   If in type C And the description in the constant 、 Simple names match the method , Then check the access rights , If it passes, it returns the direct reference to this method , The search process is over ; If it doesn't go through , Then return to java.lang.IllegalAccessError abnormal .

   otherwise , According to the relationship of inheritance, you should treat C Each parent class of 2 Step by step search and verification process .

   If you never find the right way , Throw out java.lang.AbstractMethodError abnormal .

IllegalAccessError Introduce

   A program attempts to access or modify a property or call a method , You don't have access to , It usually causes compiler exceptions . If this error occurs at runtime , It means that an incompatible change has taken place in a class .

Method call : Virtual method table

   In object-oriented programming , Dynamic dispatch will be used frequently , If you have to search for the right target in the method metadata of the class in each dynamic dispatch process, the execution efficiency may be affected . therefore , To improve performance ,JVM Create a virtual method table in the method area of the class (virtual method table)( Non virtual methods don't appear in tables ) To achieve , Use index tables instead of looking up .

   Each class has a virtual method table , The table contains the actual entries for each method .

When was the virtual method table created ?

   The virtual method table is created and initialized during the link phase of class loading , After the initial value of the class variable is ready ,JVM The method table of this class will also be initialized .

   As shown in the figure , When a method is overridden in a class , When calling , It will look directly in the virtual method table , Otherwise, it will be connected directly to Object The methods of .

Method return address

   The return address of the method is : Call the superior method of the method PC The value stored in the register .

   The end of a method , There are two ways :

    1. Normal execution complete

    2. An unhandled exception occurred , Abnormal exit

   Whatever way you exit , After the method exits, it returns to the location where the method was called . When the method exits normally , Of the caller PC The value of the counter is used as the return address , That is, the address of the next instruction of the instruction calling the method . And by the exception of the exit , The return address is determined by the exception table , This part of information will not be saved in stack frame .

When a method starts executing , There are only two ways to exit this method :

  ① The execution engine encountered a bytecode instruction returned by any method (return), There will be a return value passed to the upper level method caller , The export is normally completed .

    A method after the normal call is completed , Which return instruction do you need to use , It also depends on the actual data type of the method return value .

   In bytecode instructions , The return instruction contains ireturn( When the return value is boolean,byte,char,short and int Use ),lreturn(Long type ),freturn(Float type ),dreturn(Double type ),areturn( Reference type ). There's another one return The directive is declared as void Methods , Instance initialization method , Class and interface initialization methods use .

  ② Exception encountered during method execution (Exception), And this exception is not handled in the method , That is, as long as no matching exception handler is found in the exception table of this method , Will cause the method to exit , For short, the export is completed abnormally .

    During method execution , Exception handling when an exception is thrown , Stored in an exception handling table , It is convenient to find the code to handle the exception when an exception occurs .

   Essentially , Method exit is the process of the current stack frame out of the stack . here , Need to restore the local variable table of the upper method 、 The stack of operands 、 Push the return value into the operand stack of the caller stack frame 、 Set up PC Register values, etc , Let the caller method continue to execute .

   The difference between a normal completion exit and an abnormal completion exit is that : Exit through exception will not produce any return value to its upper layer callers .

Some additional information

   Stack frames are also allowed to carry with Java Some additional information about virtual machine implementation . for example : Information to support program debugging .

Relevant interview questions

For example, stack overflow ?

  (StackOverflowError)

How to set the stack size ?

   adopt -Xss Parameters .

Adjust stack size , Can we ensure that there is no overflow ?

   There is no guarantee that it will not overflow .

The larger the stack memory allocated, the better ?

   No , The larger the stack memory allocation , In a certain period of time, it decreased OOM probability , But it will crowd out other threads , Because the whole memory space is limited .

Does garbage collection involve virtual machine stack ?

   Thread private , Don't involve .

Whether the local variables defined in the method are thread safe ?

   If the object is generated internally , And die inside , No return to the outside , So it's thread safe , Otherwise, it is thread unsafe .

Run time data area , Whether there is Error and GC?

 

版权声明
本文为[There's a bastard in the north of the city]所创,转载请带上原文链接,感谢
https://cdmana.com/2020/12/20201224085539184e.html

Scroll to Top