The JVM StackMapTable Past and Present

JVM Java 6 version introduced after the class files in the stack diagram (StackMapTable).

  • Effect
    in order to improve the efficiency of the verification process in the JVM type checking

FIG stack structure is located Code attribute (attribute refers Classfile Code) of the attribute table (attributes table) structure. StackMapTable contain at most one attribute in the attribute byte codes in the Code.
After the Java 7 version as a mandatory part of the stack of the byte code file. Originally programmers do not need to care about the details of the JVM JIT compiler, you do not know compiler theory or data flow, control flow details. However, a stack of the force, to be generated if the bytecode The, must be accurately known for each bytecode instruction corresponding to the type of local variables and operand stack. This is because Java7 at compile time to do some things during the verification done, and that is the type of inspection, which is included in the content stack diagram.

But Java's class loading time validation run only once, and accounted for most of the time the operation is IO consumption, rather than the verification process. Even now with the stack of the verification process will still be executed, there is a stack diagram is only part of the verification time savings. And designers must also be compatible JVM implementing verification does not stack diagram, because Java7 the previous version is not mandatory stack diagram of the concept, however Java8 still continues bytecode stack structure diagram.

mally, you do not need to know much about the stackmap Table when using ASM. ASM can automatically generate this table for you unless you initialize the classwriter with COMPUTE_FRAME flags.For detailed table definition, you can consult the JVM specification (After Java7? ). The only place I know for the stackmap table is the bytecode verification when a class loader is about to load a bytecode, or you want to see the legal of bytecode you generated. In this case, verifier takes the entries in the table to make the correctness of bytecodes (e.g., type consistence, jump targets and so on). Check this link http://stackoverflow.com/questions/25109942/is-there-a-better-explanation-of-stack-map-frames if you want to detail explanation.

Let's look at an example of a combined structure of the stack of FIG.

Java code is as follows:

package bytecode;

public class Coffee {
 
    int bean;
 
    public void getBean(int var) {
        if (var > 0) {
            this.bean = var;
        } else {
            throw new IllegalArgumentException();
        }
    }
 
}

Use Verbose to see the Class file structure is as follows: look at the focus StackMapTable, stack diagram contains two entry.

public class com.lijingyao.bytecode.Coffee
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#18         // java/lang/Object."<init>":()V
   #2 = Fieldref           #5.#19         // com/lijingyao/bytecode/Coffee.bean:I
   #3 = Class              #20            // java/lang/IllegalArgumentException
   #4 = Methodref          #3.#18         // java/lang/IllegalArgumentException."<init>":()V
   #5 = Class              #21            // com/lijingyao/bytecode/Coffee
   #6 = Class              #22            // java/lang/Object
   #7 = Utf8               bean
   #8 = Utf8               I
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               getBean
  #14 = Utf8               (I)V
  #15 = Utf8               StackMapTable
  #16 = Utf8               SourceFile
  #17 = Utf8               Coffee.java
  #18 = NameAndType        #9:#10         // "<init>":()V
  #19 = NameAndType        #7:#8          // bean:I
  #20 = Utf8               java/lang/IllegalArgumentException
  #21 = Utf8               com/lijingyao/bytecode/Coffee
  #22 = Utf8               java/lang/Object
{
  int bean;
    descriptor: I
    flags:


  public com.lijingyao.bytecode.Coffee();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 6: 0


  public void getBean(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: iload_1
         1: ifle          12
         4: aload_0
         5: iload_1
         6: putfield      #2                  // Field bean:I
         9: goto          20
        12: new           #3                  // class java/lang/IllegalArgumentException
        15: dup
        16: invokespecial #4                  // Method java/lang/IllegalArgumentException."<init>":()V
        19: athrow
        20: return
      LineNumberTable:
        line 10: 0
        line 11: 4
        line 13: 12
        line 15: 20
      StackMapTable: number_of_entries = 2
        frame_type = 12 /* same */
        frame_type = 7 /* same */
}

The constant pool table structure can be seen Classfile structural properties utf8 # 15 designates StackMapTable structure. Can be seen in the last few lines getBean (int) method
specific StackMapTable structure, this is the stack of FIG. From the above it found StackMapTable contains attribute_name_index, attribute_length, number_of_entries structure and entries. Number_of_entries which represents the number of stack map frame, i.e. the number of entries It, can be seen in this example there are two "frame_type" i.e., = 2. The two entries are = 12 is the frame_type / * Same / =. 7 and the frame_type / Same /. Each entry represents the StackMapFrame element of a method. Which contains a byte offset code (indicating that the frame position corresponding to the byte code) and the local variable table at this offset (local variables), the operand stack (operand stack entry) type of authentication required (ps: the local variable table and on the operand stack may refer to the introduction of http://blog.csdn.net/lijingyao8206/article/details/46562933). The first method is a StackMapFrame each implicit (entries [0]), and is calculated by the described method of the type checker. Here we see = 12 frame_type / Same, * / in fact, is the second StackMapFrame method, but is StackMapFrame displayed. Each stack map frame entries in the table are dependent on the previous element, each of which is used to represent the incremental offset. Therefore, the order of entry is very important.

Here to add that bytecode instructions and parameters concepts, bytecode instructions, the opcode mnemonics represented by a byte length (the Opcode) and its subsequent configuration operation need several parameters. Some instructions do not necessarily need parameters. But here careful not to confuse a concept, parameters and operands (oprends) is not a concept here is the same. Where the arguments (parameters) values ​​are static, compile the bytecode is stored in the compiled, and the operand stack Oprends (operand) values ​​described in the first run of values ​​to know the data structure. I do not know is not clear, but found a lot of articles and translations are confusing instruction set "parameters" and operand stack "operand." In fact, based on a parameter bytes signed integer, used to point to jump target addresses, if more than one byte, in order to store two parameters, or the two parameters in such manner endian storage. Such as: target instruction address + = goto instruction address (parameter 1 << 8 | 2 parameters).

Because the stack map frame structure in FIG stack entries are used to identify the incremental offset can be calculated according to each display frame offset of a frame is displayed according to formula offset_delta + 1. I.e. getBean example of a method to offset this calculation, entries first item displayed in the present example: frame_type = 12, where 12 is the one byte code offset (offset_delta) frame is. The offset to the next element is offset_delta + 1 + offset of the current frame the previous element. So we see

1: ifle 12
this line, the parameter ifle absolute expression bytecode instructions is 12, so the bytecode offset entries of the first element is StackMapFrame offset_delta = 12, empathy

9: goto 20
This parameter bytecode instructions goto line 20 is, in fact, goto 12 + 1 + 7, i.e. the byte code instruction is offset goto 20. Therefore, by recording the offset StackMapTable to ensure byte order, and are not duplicated. Can be found, but to the JVM StackMapTable type checking verification stage adds some bytecode instructions for the offset information calculated by the increment, the method simplifies the inspection of all bytes of code offsets.

Frame_type / * same * / This Example represents the StackMapFrame current frame and a previous frame have the same local variables, and the current operand stack is empty.
In this paper, combined with JVM 8 specification, if wrong, please correct me.

Published 404 original articles · won praise 1022 · Views 500,000 +

Guess you like

Origin blog.csdn.net/qq_33589510/article/details/105248897