InsideJVM (5) -java stack (stack)

zhaozj2021-02-11  229

Java stack JVM allocates a stack for each newly created thread. The stack saves the state of the thread in a frame-based unit. JVM only performs two operations on the stack: stack and out of the stack in frames.

The method that a thread is performing is called the current method of this thread. The current method is called the current frame. The class belongs to the current method is called the current class. The constant pool of the current class is called the current constant pool. When the thread performs a method, it tracks the current class and constant pool. When the JVM performs the operation of intra data within the current frame.

When the thread activates a Java method, the JVM will press a frame in the Java stack of the thread. This frame naturally became the current frame. This frame will be used to save parameters, local variables, intermediate calculation processes, and other data during this method.

One method can end in two ways. One is the end of the normal return. One is an abnormality ending (Abrupt Completion). Regardless of the way, JVM will pop up the current frame and release it, so that the frame of the previous method becomes the current frame. (Translator: It may be possible to understand, the frame located at the top of the stack is the current frame)

All data on the Java stack is privately available. A thread cannot access the stack data of another thread, so if you do not need to synchronize the stack data in the case of multi-thread.

Like method area and heap (see previous translation), Java stacks and frames do not have to be continuous in memory. The frame can be distributed in a continuous memory area or not. The data structure of the frame is determined by the implementation of the JVM, which allows the user to specify the initial size or maximum minimum size of the Java stack.

The Stack Frame Stack Frame has three parts: local variable area, operand stack, and frame data area. The local variable zone and the size of the operand stack should be determined by the corresponding method. The compiler calculates each method when compiling and placed in the class file. The size of the frame data area is certain for a JVM implementation. When the JVM activates a method, it obtains the size of the local variable area of ​​this method from class information data and the size of the operand stack, and the size of the appropriate stack frame is pressed into the Java stack accordingly.

The local variable area of ​​the local variable zone Java stack frame is an array of zero types for a word. The instructions use this data by index. The value of INT, FLOAT, REFERENCE and RETURNADDRESS occupies an array, and the value of type Byte, Short, and Char is turned to an int value before depositing in an array. The value of the type long and double occupies two consecutive items, when accessing them, the instruction provides the index of the first item. For example, a long value occupies 3, 4, and the instruction will take the LONG value of the index 3. All the values ​​of the local variable zone are all words, and the starting index values ​​of Long and Douplas are not limited.

The local variable zone contains the parameters and local variables of this method. The compiler first places the parameters in the local data area in the order of declaration. Figure 5-9 shows the variable zone of the following two methods. // ON CD-ROM IN File JVM / EX3 / EXAMPLE3A.JAVACLASS EXAMPLE3A {

Public Static Int RunclassMethod (INT I, Long L, Float F, Double D, Object O, BYTE B) {

Return 0;}

Public Int RuninstancethMethod (Char C, Double D, Short S, Boolean B) {

Return 0;}}}

Figure 5-9. Method parameters in the local variable area

Note that in the frame of the method runinstanceMethod (), the first parameter is a value of a type Reference, although the method does not display the parameters, but this is a parameter that is implicitly added to each instance method (Instance method) Value, used to represent the call to the call. (Translator: Like the THIS pointer in C ) We look at RunclassMethod () does not have this variable, because this is a class method, class method and class, not related to the object. We noticed Byte, Short, Char, and Boolean in the source code into INTS in the local variable area. The same situation is also the same. As mentioned earlier, JVM does not directly support the Boolean type, and the Java compiler always uses INTS to represent Boolean. However, Java is supported by Byte, Short and Char, which can be stored as an instance variable in a local variable area, or may be stored as class variables in the method area. However, in the local variable zone and the operand stack, it is converted to the value of the INTS type, and the operation is also int click, only when the reactor or method area will turn back to the original type.

It is also necessary to pay attention to the object O of RunclassMethod (). In Java, the object is passed in Reference. All objects are stored in the heap, you will never find the copy of the object in a local variable area or operand stack, and there will be an object reference.

The compiler can be used in a variety of placement methods of local variables, which can arbitrarily determine the order sequence, and can even use an index to refer to two local variables. For example, when the scope of the two local variables do not overlap, such as the local variables I and J of Example 3b.

// ON CD-ROM IN File JVM / EX3 / EXAMPLE3B.JAVACLASS EXAMPLE3B {

Public static void runtwoloops () {

For (int i = 0; i <10; i) {system.out.println (i);

For (int j = 9; j> = 0; --j) {system.out.println (j);}}}

The implementation of JVM is still the same flexibility like other data regions. How to distribute the long and double data in an array, the JVM specification is not specified. If a JVM implemented word length is 64 bits, you can put the long or double data in the number in the array, and the high item is empty. (When the word length is 32, it is necessary to put down a long or double).

The operand stack operand is the same as a local variable region that stores data with an array of Word, but it is not accessed by an index, but is pressed and popped in a stack. If an instruction is pressed into a value, another instruction can pop up this value and use it.

JVM is the same as the processing data type in the operand stack, and the local variable zone is the same as the conversion of data types. The JVM does not have a register, and the JVM is based on the stack rather than registers, because JVM's instructions get operands from the stack, not registers. Although operands can be obtained from other places, such as by nodes, or within a constant pool, but mainly from the stack.

JVM uses the operand stack as a work area. Many instructions pop up data from this stack, perform operations, and then press the result. For example, the IADD instruction pops up from the stack, adds, then press the result. The following shows how JVM performs this action: iLoad_0 // push the int in local variable 0iload_1 // push the int in local variable 1iadd // Pop Two INTS, Add THEM, PUSH RESULTISTORE_2 / / POP INT, Store Into Local Variable 2 In the sequence of this bytecode, the first two instructions iLoad_0 and iLoad_1 will be stored in the integer of the index of 0 and 1 in the local variable zone, and then add, press the result into the operational data area. in. Article 4 Instructions ISTORE_2 pops up from the operation data area and stores the local data area index of 2. In Figures 5-10, the process is described in detail, in the figure, the area where the use is expressed in a blank.

Figure 5-10. Two partial variables are added.

In addition to the local variable zone and the operation data stack, Java stack frame also requires data to support constant pool resolution, normal returns and exception distributions (Exception Dispatch). This information is saved in the frame data area.

Many instructions in the JVM involve data on a constant pool. Some instructions are merely removed in the constant pool and press into the operand stack. Some instructions use data in the constant pool to indicate the class or array that needs to be instantiated, the domain that needs to be accessed, or the method that needs to be activated. There are also some instructions to determine if an object is a descendant example of a certain class or interface specified by a constant pool.

Whenever JVM is required to perform an instruction that requires constant zone data, it will access the constant region through a pointer to the constant zone in the frame data area. Previously, the references for types, domains, and methods were symbols at the beginning of the constant zone. If it is still a symbol when the instruction is executed, the JVM will parse.

In addition to the constant zone parsing, the frame data area also helps the JVM processing method to end the normal and exception. Normal end, JVM must restore the environment of the method caller, including recovering the PC pointer. If the method has a return value, the JVM must press the value to press the value of the operand's operator stack.

In order to handle the abnormality of the method, the frame data area must save a reference to this method's exception table. An exception table defines this method being protected by the Catch clause, each of which has the start and start position of the CatCH clause, and the index used to represent an exception class in a constant pool, and the Catch clause The starting position of the code.

When a method throws an exception, JVM uses the exception table specified by the frame array area to determine how to handle it. If you find a matched Catch clause, you will turn over the control. If not found, the method will end immediately. JVM uses the information of the frame data area to restore the caller's frame and then reappears the same exception.

In addition to the above information, the implementation of the JVM can also place additional information into the frame data area, such as debug data.

A implementation of a Java stack can design a Java stack in your own idea. As previously, a method is a separate distribution frame from the heap. I take this as an example, look at the following: // ON CD-ROM IN File JVM / EX3 / EXAMPLE3C.JAVACLASS EXAMPLE3C {

Public static void addandprint () {double result = addtwotypes (1, 88.88); system.out.println (result);}

Public Static Double AddTTTWOTYPES (INT I, DOUBLE D) {Return i D;}} Figure 5-11 shows three snapshots for performing this method. In this JVM implementation, each frame is individually assigned from the heap. In order to activate the method addTwotypes (), method addandprint () first press the INT 1 and Double88.88 to the operand stack, and then activate the addtwotypes () method.

Figure 5-11. Frame distribution

The command of activation addtwotypes () uses the data of the constant pool, and the JVM finds that this data in the constant pool is resolved if necessary.

Note that addandprint () method uses constant pool reference method addtwotypes (), although these two methods belong to a class. Like other classes, reference to the same class and the domain reference are also symbols in the initial time, which needs to be parsed before use.

The parsed constant pool data item will point to information stored in the method area for information on how to addTWotypes (). JVM will use this information to determine the size of the ADDTWOTYPES () local variable area and the operand stack. If you use Sun's Javac compiler (JDK1.1), the local variable area of ​​the method addTwotypes requires three words, and the operand stack requires four words. (The size of the frame data area is set to a JVM implementation) JVM assigns a stack frame that is sufficiently sized for this method. The Double parameters and int parameters (88.88 and 1) are then popped up from the operating status stack of the method AddandPrint (88.888 and 1) and put them in the local variable area index of the method addtwotype () to 1 and 0.

When addtwotypes () returns, it first presses the return value of the type Double (here 89.88) into its operand stack. JVM uses the information in the frame data area to find the caller (for addandprint ()), then press the return value into the opener stack in the AddandPrint () and releases the stack frame of the method AddTwotype (). The JVM then makes the stack frame of the addtWotype () as the current frame and proceeds to execute method addandprint ().

Figure 5-12 shows the same method in different JVM implementations. The stack frame here is in a continuous space. This method allows the stack frame of the adjacent method to overlap. Here, the caller's operand stack is a local variable zone of the tuner.

Figure 5-12. Assigning frames from a continuous stack

This method not only saves space, but also saves time because JVM does not have to copy the parameters from a stack frame to another stack frame.

Note The operating number stack of the current frame is always at the top of the Java stack. Although this may be better illustrated in Figure 5-12. However, regardless of how the Java stack is implemented, the operation of the operand stack is always performed at the current frame. In this way, the operand stack in the current frame is pressed into a value in the Java stack.

There are still other implementations of the Java stack, essentially of the above two types. A JVM can divide a space from the stack at the beginning of the thread. In this continuous space, JVM can use 5-12 overlap. However, in combination with other segment space, the method of Figure 5-11 is used.

转载请注明原文地址:https://www.9cbs.com/read-5636.html

New Post(0)