During the function call and access the stack

Procedure function calls

The basic thread of execution behavior is a function call, each function call data are passed through the Java stack. Stack on the Java stack data structure similar sense, it is out after an advanced data structures, support only pushed and popped two operations. The main content of Java stack is the stack frame. Each function call, there will be a corresponding stack frame is pushed onto the Java stack, each function call ends (either return to normal or throw an exception), there will be a stack frame is popped Java stack.

As shown in Fig 2 functions in a function call, the function calls the function 3 2, 3 functions 4 calls the function. A function is called, a stack frame stack; 2 function is called, the stack frame Drawing 2; 3 function is called, the stack frame Drawing 3; 4 function is called, the stack frame Drawing 4; 4 function call is completed, the stack stack frame 4; 3 function call is completed, the pull stack frame 3, until the function of a stack.

1565679392532

It is generated corresponding to each function call stack frames, which can take some memory. Since the HotSpot VM does not distinguish between Java native method stacks and stacks, stack memory is set by -Xss parameters. About Java native method stacks and stacks, defines two exceptions in the Java Virtual Machine Specification.

  • Requesting a stack depth greater than the threads of the virtual machine allowable depth, will throw exception StackOverflowError
public class StackDeepTest {

    private static int count = 0;

    public static void recursionCall() {
        count ++;
        recursionCall();
    }

    public static void main(String[] args) {
        try {
            recursionCall();        
        }catch(Throwable ex) {
            System.out.println("调用了:"+count);
            ex.printStackTrace();
        }
    }

}

Use -Xss128k parameters, the result is "a call: 1089" when using -Xss256k parameters, the result is "a call: 3546." The number of calls after the big change parameter description can be significantly increased.

  • When the virtual machine at the time of application to extend the stack can not have enough memory, it will throw an OutOfMemoryError
public class StackOOMTest {

    public static void main(String[] args) {
        while(true) {
            Thread th = new Thread(()->{
                while(true) {}

            });

            th.start();
        }   
    }
}

No demonstration of it, there is execution risk, leading to computer stuck. In the "in-depth understanding of the Java Virtual Machine" in the given OOM exception.

Data contents of the stack frame

Method calls into the JVM to execute the bytecode, the bytecode instructions performing data structure is the stack frame (stack frame). That is the element stack in a virtual machine stack. The opportunity to assign a virtual stack frame for each method, because the virtual machine stack is a LIFO (last in, first out), so the thread is currently active stack frame, stack frame that is top of the stack, JVM specification called "CurrentFrame" this stack frame corresponding to the current method is "CurrentMethod". Perform an operation code byte, the operation is refers to the current stack frame of the data structure.

Data structure the stack frame is divided into four parts: the local variable table, the operand stack, and a method for dynamic link return address (including normal and abnormal call completion result calls)

Local variable table

Local variable table for function arguments and local variables. Local variable table variable is only valid in the current function call, when the end of the function call, along with the destruction of the function stack frame, the local variable table will also be destroyed. Local variables and operand stack table at compile capacity is determined, and by using the attribute code stored and supplied to the stack frame associated methods.

Local variables in the stack frame is standard slots can be reused, if a local variable table over its scope, the variable declaration after its scope is very likely to reuse local variable slot expired table to achieve the purpose of saving resources. Local variable table variables are also important for garbage collection root object as long as the local variable table referenced directly or indirectly, will not be garbage collected.

public class StackVarTest {

    private static final int CAPACITY = 6*1024*1024;
    
    public static void test1() {
        byte[] a = new byte[CAPACITY];
        System.gc();
    }
    
    public static void test2() {
        byte[] a = new byte[CAPACITY];
        a=null;
        System.gc();
    }
    
    public static void test3() {
        {
            byte[] a = new byte[CAPACITY];          
        }
        System.gc();
    }
    
    public static void test4() {
        {
            byte[] a = new byte[CAPACITY];
        }
        int b = 10;
        System.gc();
    }
    
    public static void test5() {
        test1();
        System.gc();
    }
    
    public static void main(String[] args) {
        test3();
        System.err.println("----------");
        test4();
    }
}

Parameters -XX: + PrintGC, results are shown below. Test3 can see no GC, test4 have GC. Test3 before performing garbage collection, although a has left the scope, but still a variable local variable table, and this point is also a byte array, so that the array can not be garbage collected. B test4 variable declared a multiplexed slot, resulting in a local variable table does not exist, it can be garbage collected

[GC (System.gc())  8140K->6784K(125952K), 0.0024535 secs]
[Full GC (System.gc())  6784K->6672K(125952K), 0.0055990 secs]
----------
[GC (System.gc())  13482K->6704K(125952K), 0.0005817 secs]
[Full GC (System.gc())  6704K->528K(125952K), 0.0282544 secs]

Operand stack

Like the local variables and the operand stack is organized into a word-wide array. But the former and different is that it is not accessible through the index, but by the standard stack operations - push and pop - to visit. For example, if a command to put a value onto the operand stack, pop up later by another instruction can use this value. Is different from the program counter, Java virtual machine does not register, program counter can not directly access the program instructions. Java virtual machine instruction is not made operand from the operand stack from the register, so that the operation mode is based instead of stack-based register. While instruction operands may be acquired from other places, such as following or, but mainly from the operation of obtaining the operand stack from the constant pool after the opcode byte (byte representing instructions) from the bytecode stream number.

Stack frame when you just created, operand stack is empty. Some Java virtual machine bytecode instruction copies the constant or variable fields from the local variable table value or object instance to the operand stack, also provides some instructions for removal of data from the operand stack, operating data, and the operation The results re-stack. Method call, prepare the operand stack is also used to accept the call parameters and the method returns the result of the method.

Dynamic Link

The interior of each stack frame contains a reference to the type of the current method where the runtime constant pool of the current code so as to achieve a method of dynamic linking . In the class file, a method to call other methods, or access member variables, you need to represent dynamic link role is to convert these methods to symbolic references represented as a direct reference to the actual method by symbolic references. Not to resolve unresolved reference symbols in the class loading procedure, and accesses the conversion will be stored in a variable access these variables. When the loading phase transformation or use for the first time directly referenced (when the variable access translated into run storage structure to access these variables where the memory location) is called static resolution. Dynamic Link also supports the JVM runtime into a direct reference. Also called Late Binding, late binding.

Methods return address

Method returns the return value of the operand will press the stack frame of the caller's stack, the counter value of the PC will be adjusted to the method call an instruction following instruction. This makes the current stack frame and the caller can connect and make the operation of stack stack frame of the caller to continue down.

Abnormal method call is completed, primarily JVM ran out exception if the main exception is not caught, or face athrow bytecode instructions displayed thrown, then it will not have a return value back to the caller.

Allocated on the stack

Allocated on the stack is a Java virtual machine optimization technology provided by its basic idea is: to target those threads private (refer to objects can not be accessed by other threads to), you can assign them to break up the stack, rather than allocated on the heap. The benefit is a function call can be completed in a self-destruct without garbage payback intervention, thereby improving system performance.

Technical base assignment on the stack is escape analysis. The object of the escape analysis determines whether the object is likely to escape the scope of the function thereof. p1 is a member variable, this field can be accessed by any thread, the object belonging to escape; P2 is a local variable, and is not returned, it did not happen escape this situation, the object could be allocated on the stack, rather than heap.

public class StackObjectTest {

    static class Person{
        public String name;
        public int age;
    }
    
    private Person p1;
    
    /**
     * 逃逸对象
     */
    public void alloc1() {
        p1 = new Person();
        p1.age=23;
        p1.name="ss";
    } 
    
    /**
     * 非逃逸对象
     */
    public static void alloc2() {
        Person p2 = new Person();
        p2.age=23;
        p2.name="ff";
    } 
        
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for(int i=0; i<1000000000; i++) {
            alloc2();
        }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
    
}

For a large number of small objects scattered allocated on the stack provides a good object optimum allocation strategy, fast speed distribution on the stack, and can effectively avoid the negative effects caused by garbage collection, and heap space but is small compared stack space and therefore not suitable for large objects can not be allocated on the stack.

Guess you like

Origin www.cnblogs.com/fzsyw/p/11347855.html