Welcome to github.com/hsfxuebao/j… , hope to help you, if you feel ok, please click on the Star

From: www.cnblogs.com/xjwhaha/p/1…

1. An overview of the

One of the most impressive things about the JVM is the stack and heap, which are the two largest memory hogs in the JVM.

At a macro level, the stack is the unit of runtime, while the heap is the unit of storage, and the stack solves the problem of how the program executes, or how it processes data. The heap solves the problem of data storage, where and where data is stored.

So why is the runtime data structured as a stack for the JVM

  1. Due to the cross-platform design, Java instructions are designed according to the stack structure. Different platforms have different CPU architectures, so they cannot be register-based.
  2. Advantages are cross-platform, small instruction set, compiler easy to implement, disadvantages are performance degradation, to achieve the same function requires more instructions.

Back to the top

2. Store content

Java Virtual Machine Stack (Java Virtual Machine Stack), also known as the Java Stack. When each thread is created, it creates a virtual machine Stack, which holds Stack frames. Each Stack Frame corresponds to a Java method call.

Stacks are thread-private, created as a thread is created and destroyed as a thread is introduced

Function:

Manages the execution of a Java program, which holds local variables of a method (eight basic data types, reference addresses of objects), partial results, and participates in method calls and returns.

Features:

The stack is a fast and efficient way to allocate storage, second only to program counters in access speed. There are only two direct JVM operations on the Java stack:

  1. Each method executes with a push (push, push)

  2. Exit the stack after execution

Therefore, there is no garbage collection problem in this space of the virtual stack, but there is the possibility of memory overflow

Back to the top

3. The VM stack memory is faulty

The Java Virtual Machine specification allows the size of the Java stack to be dynamic or fixed. If fixed length is specified, the maximum size of each vm stack can be specified at JVM startup

Use the -xSS option to set the maximum stack size for a thread. The stack size directly determines the maximum reachable depth of a function call.

-Xss1024m // Stack memory is 1024MB -Xss1024k // Stack memory is 1024KBCopy the code

Code examples:

This is a piece of code that’s going to make an infinite recursive call, and it’s going to push the stack indefinitely, and eventually it’s going to run out of stack memory,

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

No initial parameters are set and the program overflows after 11418 recursions

When we set the stack memory to 256KB, it overflowed after 2471 recursions

Possible exceptions in the stack

  1. The Java virtual machine will throw a StackoverflowError if the thread request allocates more stack capacity than the maximum allowed by the Java virtual machine stack.
  2. An OutofMemoryError will be thrown if the Java virtual machine stack can be dynamically extended and cannot allocate enough memory when attempting to extend it, or if there is not enough memory to create the corresponding virtual machine stack when creating a new thread.

Back to the top

4. Operation principle of stack

As mentioned above, each thread has its own Stack, and the data in the Stack is in the format of Stack frames. Each method being executed on this thread has a Stack Frame. A stack frame is a block of memory, a data set that holds various data information during the execution of a method.

What if the stack works while the program is running:

  1. The JVM operates directly on the Java stack only two times, pushing and unloading frames, following the fifo (lifO, first out) principle
  2. In an active thread, there is only one active stack frame at a time. That is, only the stack frame (top stack frame) of the currently executing method is valid
    • This stack Frame is called the Current Frame.
    • The Method corresponding to the Current stack frame is the Current Method
    • The Class that defines this method is the Current Class
  3. All bytecode instructions run by the execution engine operate only on the current stack frame.
  4. If another method is called in this method, a new stack frame is created and placed at the top of the stack as the new current frame.
  5. The stack frames contained in different threads are not allowed to reference each other, that is, it is impossible to reference another thread’s stack frame in one stack frame.
  6. If the current method calls another method, 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 will discard the current stack frame, making the previous stack frame become the current stack frame again.
  7. Java methods have two ways of returning functions, but either way will result in the stack frame being ejected
    • One is to return a normal function, using a return instruction (even if the return value is defined as void, the method ends with a return).
    • The other is to throw an exception

Back to the top

5. Internal structure of stack frames

According to the above content, the unit stored in the stack is each stack frame corresponding to each method, so what structure is inside each stack frame

  1. Local Variables
  2. Operand Stack (or expression Stack)
  3. Dynamic Linking (method reference pointing to the runtime constant pool)
  4. Method Return Address (definition of normal or abnormal method exit)
  5. Some additional information

Back to the top

6. Local variation scale

  1. Local Variables: Local Variables are called Local variable arrays or Local Variables
  2. Is defined as a numeric array (because other data types can be stored using numeric types) that stores method parameters and local variables defined in the method body. These data types include various primitive data types, object references, and returnAddress types.
  3. Since the local variable table is built on the stack of the thread, it is the thread’s private data, so there is no data security problem
  4. The size required by the local variables table is determined at compile time and stored in the Maximum Local Variables data item in the Code attribute of the method. The size of the local variable scale does not change during method execution.
  5. The number of nested calls to a method is determined by the stack size. In general, the larger the stack, the more nested method calls.
    • For a function, the more parameters and local variables it has, which causes the local variable table to swell, the larger its stack frame will be to meet the need for more information to be passed through method calls.
    • In turn, function calls take up more stack space, resulting in fewer nested calls.
  6. Variables in the local variable table are only valid in the current method call.
    • During method execution, the virtual machine passes the parameter values to the parameter variable list using the local variable table.
    • When the method call ends, the local variable table is destroyed along with the method stack frame.

Why is the size of the local variable scale already determined at compile time

Code:

public class LocalVariablesTest { private int count = 0; public static void main(String[] args) { LocalVariablesTest test = new LocalVariablesTest(); int num = 10; test.test1(); } public void test1() { Date date = new Date(); String name1 = "atguigu.com"; test2(date, name1); System.out.println(date + name1); } public String test2(Date dateP, String name2) { dateP = null; name2 = "songhongkang"; Double weight = 130.5; // Gender = 'male '; return dateP + name2; }}Copy the code

Bytecode instructions parsed using Javap:

So, at compile time, the number of local variables, the size of each local variable is recorded, and the size of the local variable table is determined at compile time

Back to the top

7. Use the Jclasslib plugin to view the class bytecode

We need to look at some of the method descriptions in the bytecode file, but the native bytecode is not very pretty. You can use the jclasslib tool for IDEA

Example code: The very ordinary main method

public static void main(String[] args) {
        LocalVariablesTest test = new LocalVariablesTest();
        int num = 10;
        test.test1();
}
Copy the code
  1. Method name return value type, permission modifier

  1. This method is a bytecode instruction set

  1. Method Exception information table

  1. Other items (local variable table length, bytecode instruction length)

  1. The mapping between the bytecode instruction line number and the original Java code line number

  1. Where a local variable takes effect in a bytecode instruction and for what length

Back to the top

8. Slot Slot

As mentioned above, local variables are stored in the local variable table, and the local variable table is stored as Slot

  1. Parameter values are always stored from the index 0 of the local variable array to the index -1 of the array length (the local variable list is itself an array).
  2. The most basic storage unit of a local variable table is Slot, which stores variables of the basic data types (8 types), reference types and returnAddress types known at compilation time.
  3. In the local variable table, types up to 32 bits occupy only one slot (including the returnAddress type), and 64-bit types occupy two slots (long and double).
  4. The JVM assigns an access index to each Slot in the local variable table, which successfully accesses the value of the local variable specified in the local variable table
  5. When an instance method is called, its method parameters and local variables defined inside the method body are copied to each slot in the local variable table in sequence
  6. If you need to access the value of a 64bit local variable in the local variable table, you only need to use the previous index. (For example, to access variables of type long or double, which occupy two slots, access the index of the first slot.)
  7. If the current frame is created by a constructor or instance method, the object reference to this will be placed in slot with index 0, and the rest of the arguments will continue in the argument list order

Schematic diagram:

Example code 1:

public void test3() {
    this.count++;
}
Copy the code

As you can see, this is also stored as a local variable in the local variable table, and refers to the instance of the object that is called. This is why the constructor can access itself with the this keyword, while the static modifier does not store this variable, so it cannot be used internally

Example code 2:

public String test2(Date dateP, String name2) { dateP = null; name2 = "songhongkang"; Double weight = 130.5; // Gender = 'male '; return dateP + name2; }Copy the code

It is clear from the bytecode that the weight of type double takes up two positions and the index jumps by two places

Slot reuse problem

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

Example code:

public void test4() { int a = 0; {// the scope of b will end after the parentheses end, so the slot position int b = 0 in the local variable table will be reclaimed; b = a + 1; } int c = a + 1; }Copy the code

Back to the top

9. Classification of variables in the JVM

According to data type:

  1. Basic data types
  2. Reference data type

As declared in the class

  1. Prepare for base-type static class variables: assigning a default value to the class variable

  2. Reference type Static class variable: INITIAL stage: Explicit assignment to a class variable is static code block assignment

  3. Normal member variables (instance variables) : As the object is created, instance variable space is allocated in the heap space and assigned by default

  4. Local variables: must be explicitly assigned before they can be used! Otherwise, it doesn’t compile,

    public void test5Temp(){ int num; System.out.println(num); // Error message: num is not initialized}

It cannot be used when local variables are not initialized because objects are added to the local variable table after initialization.

added

  1. The part of the stack frame that is most relevant for performance tuning is the local variable table mentioned earlier. When a method executes, the virtual machine uses a local variable table to complete the method’s delivery.
  2. Variables in the local variable table are also important garbage collection root nodes, as long as objects referenced directly or indirectly in the local variable table are not collected.

Back to the top

10 Operand stack

Another very important component of Stack frame, Operand Stack, is also the structure of Stack **, is realized by the array **, used to save all kinds of data temporarily when the instruction is executed, many characteristics and local variable table similar

  1. Each individual Stack frame contains a last-in-first-out operand Stack, also known as the Expression Stack, In addition to the local variable table.
  2. Operand stack, during the execution of a method, data is written to or extracted from the stack according to bytecode instructions, i.e. push and pop.
  3. Some bytecode instructions push values onto the operand stack, while others push operands off the stack. Use them and then push the results onto the stack, such as copying, swapping, summing, and so on

In addition, we say that the JVM’s interpretation engine is a stack-based execution engine, where the stack refers to the operand stack. In a method, all the required local variables and so on are stored in the local variable table (including the data in the local variable table is also generated and assigned by the operand stack).

This data is then copied by bytecode instructions to the operand stack, where operations are performed, the results are stored in the operand stack, and the results are overwritten back. This is the core of how the JVM operates

Features:

  1. Operand stack, mainly used to store the intermediate results of the calculation process, and as a temporary storage space for variables during the calculation process.
  2. The operand stack is a workspace of the JVM’s execution engine. When a method is first executed, a new stack frame is created, and the operand stack of the method is empty.
  3. Each stack of operands has an explicit stack depth for storing values. The maximum depth required is defined at compile time and is stored in the method property as the value of maxStack.
  4. Any element in the stack is a Java data type that can be arbitrary
    • 32-bit types occupy one stack unit depth
    • 64-bit types occupy two stack units of depth
  5. The operand stack does not access the data by accessing the index, but only once through the standard push and push operations
  6. If the called method has a return value, the return value is pushed into the operand stack of the current stack frame and updates the NEXT bytecode instruction to be executed in the PC register.
  7. The data types of the elements in the operand stack must exactly match the sequence of bytecode instructions, which is verified by the compiler during compiler time and again during data flow analysis during class validation during class loading.

Code demo:

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

The code above parses bytecode:

 0 bipush 15 
 2 istore_1
 3 bipush 8
 5 istore_2
 6 iload_1
 7 iload_2
 8 iadd
 9 istore_3
10 return
Copy the code

Instruction execution process:

In the first statement, the PC register points to 0, that is, the instruction address is 0, and then bipush the operand 15 onto the operand stack.

At this point, the PC register points to the second instruction, which executes, and assigns data from the operand stack to the position of index 1 in the local variable table (position 0 is this).

As we continue, the operand 8 is also pushed

The next instruction also pops 8 and assigns it to the position of index 2 in the local variable table

The data is then extracted from the local variable table at positions 1 and 2, which in turn will be placed in the operand stack.

The two elements in the operand stack are then added together and stored at the location of the local variable table 3

In the above instruction, you can see that when int 8 is defined, the operand stack is of type Bytebipush 8. This is because the JVM stores data in the operand stack in the smallest possible way, with short ascending if more than bytes are stored

Instructions for calling methods and returning values to the operand stack

As described above, when a method has a return value, the return value is pushed onto the stack.

public int getSum(){ int m = 10; int n = 20; int k = m + n; return k; } public void testGetSum(){public void testGetSum(){public void testGetSum(); int j = 10; }Copy the code

At the end of the method, the ireturn instruction is executed

TestGetSum () method bytecode instruction: First load the return value of getSum()

I ++ and ++ I

This problem I believe as long as you are learning Java have encountered, generally remember to do, assignment and then operation, or operation and then assignment, so if you now use the instruction way to view, combined with the operand stack, will be very clear

i++:

int i3 = 10;
int i4 = i3++;
Copy the code

(There’s code ahead. Don’t worry about the details of the instructions.)

15 ILoad_3 // Take the value of i3 10 and push it into the operand stack 16 iinc 3 by 1 // Put i3(3 is the index of the local variable table 3) 19 istore 4 // assigns data from operand stack to i4Copy the code

So i3 is 11, and i4 is 10

++i:

int i5 = 10; int i6 = ++i5; 21 bipush 10 // push 10 into the operand stack 23 istore 5 // save 10 from the operand stack to variable i5 25 iinc 5 by 1 // variable i5 perform +1 operation 28 iload 5 // change variable i5 30 istore 6 // Store the value of the operand stack in variable i6 (11)Copy the code

So i5 and i6 are both 11

Top of stack cache technology knowledge

Stack Top cache technology: Top Of Stack Cashing

  1. As mentioned earlier, stack-based virtual machines use more compact zero-address instructions, but completing an operation requires more loading and unloading instructions, which means more instruction dispatches and memory reads/writes.
  2. Because operands are stored in memory, frequent memory read/write operations inevitably affect execution speed. In order to solve this problem, the designers of HotSpot JVM proposed Tos (top-of-stack Cashing) technology, which caches all the top-of-stack elements in the registers of the physical CPU to reduce the number of reads/writes to memory and improve the execution efficiency of the execution engine.
  3. The main advantages of registers: fewer instructions, fast execution

Back to the top

11 Dynamic Linking

Each stack frame in the stack represents a call to a method, so how to contact the method itself in the stack frame, by means of dynamic linking

  1. Each stack frame contains an internal reference to the method that the stack frame belongs to in the runtime constant pool
  2. The purpose of including this reference is to allow the code supporting the current method to achieve Dynamic Linking, such as the InvokeDynamic directive
  3. When a Java source file is compiled into a bytecode file, all variable and method references are kept as Symbolic references in the class file’s constant pool
  4. For example, describing a method that calls another method is represented by symbolic references to the method in the constant pool, so dynamic linking is used to convert these symbolic references to direct references to the calling method

Code:

public class DynamicLinkingTest { int num = 10; public void methodA(){ System.out.println("methodA()...." ); } public void methodB(){ System.out.println("methodB()...." ); methodA(); num++; }}Copy the code

Byte code:

public void methodB(); descriptor: ()V flags: ACC_PUBLIC Code: stack=3, locals=1, args_size=1 0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #6 // String methodB().... 5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;) V 8: aload_0 9: invokevirtual #7 // Method methodA:()V 12: aload_0 13: dup 14: getfield #2 // Field num:I 17: iconst_1 18: iadd 19: putfield #2 // Field num:I 22: return LineNumberTable: line 16: 0 line 18: 8 line 20: 12 line 21: 22 LocalVariableTable: Start Length Slot Name Signature 0 23 0 this Lcom/atguigu/java1/DynamicLinkingTest;Copy the code

MethodB calls methodA by using the invokevirtual directive and invoking the #7 symbol reference. MethodB calls methodA by using the #7 symbol reference and invoking the #7 symbol reference

Why use this approach:

  1. Because constants or methods can be called in different methods, you only need to store a copy and then record references to it, saving space
  2. Constant pool is used to provide symbols and constants for instruction identification

Back to the top

12 method call

12.1 Linking and Binding modes of methods

As mentioned earlier, method calls convert symbolic references in bytecode instructions into actual references to the method, so this method is called chaining, and there are two ways

  1. Static link:

    When a bytecode file is loaded into the JVM, the process of converting symbolic references to the calling method into direct references is called static linking if the target method being called is determined at compile time and the run time remains the same

  2. Dynamic linking:

    If the method to be called cannot be determined at compile time, that is to say, the symbol of the method to be called can only be converted into a direct reference during the run time of the program. Because this reference conversion process is dynamic, it is also called dynamic linking.

The Binding mechanisms of static link and dynamic link methods are: Early Binding and Late Binding. Binding is the process by which a symbolic reference to a field, method, or class is replaced with a direct reference, which happens only once.

  1. Early binding

    Early binding is invoked if the target method at compile time, and the run-time remains the same, this method can be bound with subordinate type, as a result, due to clearly define the target method is called which one on earth is, therefore, you can use the static link way of converting symbols refer to reference directly.

  2. Late binding

    If the method to be called cannot be determined at compile time, only the related method can be bound according to the actual type at run time, which is called late binding.

Dynamic linking Static linking invokes methods, often reflected in the polymorphisms of objects, as shown in the following code

** @author shkstart * @create 2020 11:59 am */ class Animal {public void eat() { System.out.println(" animal feeds "); } } interface Huntable { void hunt(); } class Dog extends Animal implements Huntable {@override public void eat() {system.out.println (" Dog eats a bone "); } @override public void hunt() {system.out.println (); } } class Cat extends Animal implements Huntable { public Cat() { super(); } public Cat(String name) {this();} public Cat(String name) {this(); } @override public void eat() {super.eat(); // Make sure that the method called is the parent's eat method, as follows: early binding system.out.println (" cat eats fish "); } @override public void hunt() {system.out.println (); } } public class AnimalTest { public void showAnimal(Animal animal) { animal.eat(); } public void showHunt(Huntable h) {h.unt (); // The hunt method of the interface, which does not determine the actual calling object, appears as: late binding}}Copy the code

The parent class represents the late binding corresponding to the class directive: invokevirtual

The late binding represented by the interface corresponds to the class instruction: InvokeInterface

This is represented by the class directive that was bound earlier: invokespecial

12.2. Method Invocation directives — Virtual and non-virtual methods

The difference between virtual method and non-virtual method

  1. If a method is called at compile time, that version is immutable at run time. Such methods are called non-virtual methods.
  2. Static methods, private methods, final methods, instance constructors, and superclass methods are all non-virtual methods **(which cannot be overridden by subclasses and behave as polymorphisms)**.
  3. Other methods are called virtual methods.

An instruction that calls a method in a virtual machine

Four general instructions:

  1. Invokestatic: Invokes static methods, and the parsing phase determines the unique method version
  2. Invokespecial: call<init>Methods, private, and methods that have not been overridden in their parent classes. The parsing phase determines the unique method version
  3. Invokevirtual: calls all virtual methods (except for final methods)
  4. Invokeinterface: Invokes interface methods

A dynamic call instruction

Invokedynamic: Dynamically resolves the method to be invoked and executes it

The difference between

  1. The first four instructions are solidified inside the virtual machine, and the method invocation execution cannot be manually interfered
  2. The InvokeDynamic directive, on the other hand, supports user-determined method versions
  3. Among them, invokestatic and Invokespecial are called non-virtual methods, and the rest (except finA1 modification) are called virtual methods.

Code examples:

/** * The invokestatic directive and invokespecial directive invoke methods called non-virtual methods * @author shkstart * @create 2020 PM 12:07 */ class Father {public Father() {system.out.println (" Father constructor "); } public static void showStatic(String str) { System.out.println("father " + str); } public final void showFinal() { System.out.println("father show final"); } public void showCommon() {system.out.println ("father "); } } public class Son extends Father { public Son() { //invokespecial super(); } public Son(int age) { //invokespecial this(); } // Is not a static method of the overridden parent class, because static methods cannot be overridden! public static void showStatic(String str) { System.out.println("son " + str); } private void showPrivate(String str) { System.out.println("son private" + str); } public void show() {invokestatic showStatic("atguigu.com"); // Invokestatic super.showStatic("good!" ); // This class private method: invokespecial showPrivate("hello!" ); // Invokevirtual is considered non-virtual because it is final and cannot be overridden by subclasses. showFinal(); // The parent class is not overridden: invokespecial super.showcommon (); // This class may have subclass overridden: invokevirtual showCommon(); info(); MethodInterface in = null; // InvokeInterface in. MethodA (); } public void info() { } public void display(Father f) { f.showCommon(); } public static void main(String[] args) { Son so = new Son(); so.show(); } } interface MethodInterface { void methodA(); }Copy the code

12.3. Invokedynamic instructions

The JVM bytecode instruction set was relatively stable until Java7 added an invokedynamic instruction, an improvement made by the JVM to implement dynamic typing language support.

What are dynamic languages and what are static languages:

Depending on whether the type check is at compile time or at run time, the former is statically typed language, whereas the other is dynamic language. To put it more bluntly, static language is to determine the type information of the variable itself, while dynamic typing language is to determine the type information of the variable value, the variable has no type information, the variable value has

Such as:

Java: String info ="Hello"; //info=Hello error JS: var name = "Hello" name = 10; Python: info = 130 // No type is specifiedCopy the code

In Java7, however, there is no way to generate invokedynamic instructions directly. You need to use ASM, the underlying bytecode tool, to generate invokedynamic instructions. Until the advent of Java8’s Lambda expressions, the generation of invokedynamic instructions, there was no direct generation in Java.

@FunctionalInterface interface Func { public boolean func(String str); } public class Lambda { public void lambda(Func func) { return; } public static void main(String[] args) { Lambda lambda = new Lambda(); Func func = s -> { return true; }; lambda.lambda(func); lambda.lambda(s -> { return true; }); }}Copy the code

Bytecode instructions: Create objects using the lambda method invokedynamic,

The dynamic language typing support added in Java7 is essentially a modification of the Java virtual machine specification, not a modification of the Java language rules. It gives the Java language a little more of the dynamic language characteristics. In general, the Java language is still a static language, and the most direct benefit is the dynamic language compiler running on the Java platform. Is the foundation of JVM support across languages

12.4. Virtual method table

The nature of method rewriting

  1. Find the actual type of the object executed by the first element at the top of the operand stack and call it C
  2. If a method of type C is found that matches both the description and the simple name in the constant, the access is verified
    • If it passes, a direct reference to the method is returned, and the search process ends
    • If not through, it returns the Java. 1 ang. IllegalAccessError anomalies
  3. If this class is not found, search and verify step 2 for each parent class of C from bottom to top according to inheritance relationship.
  4. If didn’t find the right way, it throws the Java. Lang. AbstractMethodError anomalies (such as call interface method has not been rewritten).

IllegalAccessError is introduced

  1. The program attempts to access or modify a property or call a method that you do not have access to.
  2. Normally, this will cause a compiler exception. This error, if it occurs at run time, indicates an incompatible change to a class.
  3. For example, there are JAR package conflicts in Maven

Virtual method table:

  1. In object-oriented programming, dynamic dispatch is frequently used, and it may affect the execution efficiency if you have to search for the appropriate target in the method metadata of the class during each dynamic dispatch.
  2. Therefore, to improve performance, the JVM implements this by creating a virtual Method table in the method section of the class, where non-virtual methods do not appear. Use index tables instead of lookups.
  3. Each class has a virtual method table that holds the actual entry to each method.
  4. When was the virtual method table created? The virtual method table is created and initialized during the linking phase of the class load, and the JVM initializes the virtual method table for that class after the class’s variable initializers are ready.
  5. As shown: if a method is overridden in a class, when called, it is directly looked up in the class’s virtual method table

Back to the top

13 Method returns the address

Another important area of the method stack frame is the method return address,

When method A calls method B, the instruction address of the current line of code (the value in the PC register) is stored in the information area of the method return address in method B. When the last instruction return is executed, the value is returned to the execution engine and the code after the method continues to be executed

There are two ways to end a method:

  • Normal Execution Completed
  • Unhandled exception, abnormal exit
  1. Either way, the method is returned to where it was called after it exits. When a method exits normally, the value of the caller’s PC counter is returned as the address of the next instruction that calls the method. In the case of an exception exit, the return address is determined by the exception table of the calling party. If there is no processing, it continues to be thrown up, and this information is generally not stored in the stack frame.
  2. In essence, the method exit is the process of the current stack frame out of the stack. At this point, you need to restore the local variable table of the upper method, operand stack, push the return value into the operand stack of the caller’s stack frame, set the PC register value, etc., and let the caller’s method continue to execute.
  3. The difference between a normal completion exit and an exception completion exit is that an exception completion exit does not return any value to its upper callers.

Once a method has started executing, there are only two ways to exit the method,

Normal exit:

  1. When the execution engine meets any bytecode instruction (return) returned by a method, the return value will be passed to the upper method caller, referred to as normal completion exit.
  2. Which return instruction to use after a method is normally called depends on the actual data type of the method’s return value.
  3. In the bytecode instruction, the return instruction contains:
    • Ireturn: used when the return value is Boolean, byte, char, short, or int
    • Lreturn: Long
    • Freturn: Float
    • Dreturn: Double
    • Areturn: indicates the reference type
    • Return: returns methods of type void, instance initialization methods, class and interface initialization methods

Abnormal exit:

  1. If an Exception is encountered during the execution of a method and the Exception is not handled within the method, that is, if no matching Exception handler is found in the Exception table of the method, the method will exit.
  2. During the execution of the method, the exception processing when the exception is thrown is stored in an exception processing table, which is convenient to find the code to handle the exception when the exception occurs

Exception Handling Table:

  • Decompile bytecode file to get Exception table
  • From: start address of bytecode instruction
  • To: end address of bytecode instruction
  • Target: indicates that the command whose address is 11 will be executed if an exception occurs
  • Type: The type of exception that is caught

Back to the top

14 Additional Information

In addition to the local variable table, operand stack, dynamic linking, and method address areas, the stack frame is also allowed to carry additional information related to the Implementation of the JAVA Virtual machine (see different Implementations of the JAVA Virtual machine), such as support for program debugging information

Back to the top

15 Questions about the VM stack

Stack overflow?

If the stack size is not set, the stack size can be dynamically expanded. If the stack size is not set, the stack size can be dynamically expanded. If the stack size is not set, the stack size can be dynamically expanded.

Can stack size be adjusted to prevent overflow?

No, you can only make sure that the probability of overflow is smaller, and a recursive method with no exit will always run out

Is it better to allocate more stack memory?

No, the stack area is too large and takes up too much memory data

Does garbage collection involve the virtual machine stack?

No, the stack area only on and off the stack action, memory does not need to recycle

Are local variables defined in a method thread-safe?

If an object is created internally and dies internally without being returned externally, then it is thread-safe,

If a local variable is passed in or returned, it may not be thread-safe for multiple threads outside the variable

Runtime data area, which parts have Error and GC?

Runtime data area

Is there an Error?

Whether GC exists

Program counter

no

no

The virtual machine stack

Is (SOF)

no

Local method stack

is

no

Methods area

Is (OOM)

is

The heap

Is (OOM)

is