In-depth analysis of java bytecode

Table of contents

1. Demo source code

2. Bytecode

3.class file decompile java file

4. Bytecode structure

4.1 Magic number

​Edit 4.2 version number

4.3 Constant pool

4.3.1 Constant pool counter

4.3.2 Constant pool table

​Edit 4.3.3 Constant types and structures

4.3.4 Interpretation of constants

5. Access ID

6. Class index, parent class index, interface index

7. Field table collection

 8. Method table collection

9. Property sheet collection


1. Demo source code

First, write a simple Java source code:

package com.april.test;

public class Demo {
    private int num = 1;

    public int add() {         num = num + 2;         return whether;     } }




 


2. Bytecode


To run a piece of Java source code, you must first convert the source code into a class file. The class file is a binary bytecode file compiled by the compiler for the virtual machine to interpret and execute. You can compile the source code into a class file through the IDE tool or the command line. Here we use the command line to operate, run the following command:

javac Demo.java

will generate a Demo.class file.
Let's open this Demo.class file and take a look. Notepad++ is used here, and a HEX-Editor plug-in needs to be installed.
The bytecode format file is hexadecimal, opened in excel, one cell is one byte


3.class file decompile java file


Before analyzing the class file, let's take a look at the result of decompiling the Demo.class back to Demo.java, as shown in the following figure:

 


It can be seen that the compiled source code has an empty constructor and this keyword more than the written code, why? Let go of this question first, after reading this analysis, I believe you will know the answer.

4. Bytecode structure
 

From the bytecode file above, we can see that there are a bunch of hexadecimal bytes inside. So how to interpret it? Don't worry, let's look at a table first:


This is a general structure table of Java bytecode, we can interpret it one by one according to the above order.
First of all, let's explain: the class file has only two data types: unsigned number and table. As shown in the table below:

 

The data structures of the various specific tables above will be described in detail later, so I won’t list them here for the time being.
Ok, now we start to interpret the hexadecimal of that bunch.

4.1 Magic number


As can be seen from the overall structure diagram above, the first 4 bytes represent the magic number


Magic Number

The 4-byte unsigned integer at the beginning of each Class file is called the Magic Number.
Its only function is to determine whether the file is a valid and legal Class file that can be accepted by the virtual machine. That is: the magic number is the identifier of the Class file.
The magic value is fixed at 0xCAFEBABE. will not change.
If a Class file does not start with 0xCAFEBABE, the virtual machine will directly throw the following error when performing file verification:

Using magic numbers instead of extensions for identification is mainly based on security considerations, because file extensions can be arbitrary to change.
Files in png format also have the same magic number

 


The mp3 format also has the same magic number


4.2 Version number


The 4 bytes following the magic number store the version number of the Class file. Also 4 bytes. The meaning represented by the 5th and 6th bytes is the compiled minor version number minor_version, and the 7th and 8th bytes are the compiled major version number major_version.

 Together they form the format version number of the class file. For example, if the major version number of a Class file is M and the minor version number is m, then the format version number of this Class file is determined to be Mm.


Take a look at the values ​​in our Demo bytecode:


The first two bytes are 0x0000, which means its value is 0;
the last two bytes are 0x0034, which means its value is 52.
So the above code is compiled with version 52.0, which is jdk1.8.0.
The corresponding relationship between the version number and the Java compiler is as follows


The version number of Java starts from 45, and the main version number of each JDK major version released after JDK 1.1 increases by 1

The versions corresponding to the Class files compiled by different versions of the Java compiler are different. Currently, a high-version Java virtual machine can execute Class files generated by a low-version compiler, but a low-version Java virtual machine cannot execute Class files generated by a high-version compiler. Otherwise the JVM will throw a java.lang.UnsupportedClassVersionError exception.

In actual applications, this problem may occur due to the difference between the development environment and the production environment. Therefore, we need to pay special attention to whether the JDK version compiled for development is consistent with the JDK version in the production environment when developing.

When the JDK version of the virtual machine is 1.k (k>=2), the corresponding class file format version number ranges from 45.0-44+k0 (both ends are included).

4.3 Constant pool


The constant pool is one of the most content-rich areas in the Class file. The constant pool also plays a vital role in field and method resolution in the Class file.
With the continuous development of the Java virtual machine, the content of the constant pool is also increasingly rich. It can be said that the constant pool is the cornerstone of the entire Class file.
After the version number, it is followed by the number of constant pools and several constant pool entries.

The number of constants in the constant pool is not fixed, so an unsigned number of type u2 needs to be placed at the entrance of the constant pool, representing the constant pool capacity count value (constant_pool_count). Unlike the language habit in Java, this capacity count starts from 1 instead of 0.


As can be seen from the above table, the Class file uses a pre-capacity counter (constant_pool_count) plus several consecutive data items (constant_pool) to describe the content of the constant pool. We call this series of continuous constant pool data the constant pool set.

The constant pool entry is used to store various literals and symbol references generated during compilation. This part of the content will be stored in the runtime constant pool in the method area after the class is loaded.


4.3.1 Constant pool counter


Next is the constant pool. Since the number of constant pools is not fixed and the duration is short, two bytes need to be placed to represent the constant pool capacity count value. The value of Demo is:


Its value is 0x0016, which is 22. Note that this is actually only 21 constants. The index is in the range 1-21. why?

Usually we start from 0 when we write code, but the constant pool here starts from 1, because it empties the 0th constant. This is to meet the need for some data pointing to the index value of the constant pool to express the meaning of "do not refer to any constant pool item" in specific cases. In this case, the index value 0 can be used to indicate.

4.3.2 Constant pool table


constant_pool is a table structure, with 1 ~ constant_pool_count - 1 as the index. Indicates how many constant items follow.

The constant pool mainly stores two types of constants: Literal and Symbolic References

It contains all string constants, class or interface names, field names, and other constants referenced in the class file structure and its substructures. Each item in the constant pool has the same characteristics. The first byte is used as a type tag to determine the format of the item. This byte is called tag byte (mark byte, tag byte).
Literal and symbolic references
Before interpreting these constants, we need to clarify a few concepts.
The constant pool mainly stores two types of constants: literals and symbolic references. As shown in the following table:


The fully qualified name
com/april/test/Demo is the fully qualified name of the class, just replace the "." of the package name with "/". In order to avoid confusion between multiple consecutive fully qualified names, use A ";" is generally added at the end to indicate the end of the fully qualified name. There is no semicolon after the basic data type, and there is a semicolon after the fully qualified name of the reference data type

 Simple name
The simple name refers to the method or field name without type and parameter decoration. The simple names of the add() method and the num field of the class in the above example are add and num respectively.

Descriptor
The role of the descriptor is to describe the data type of the field, the parameter list of the method (including quantity, type and order) and the return value. According to the descriptor rules, the basic data types (byte, char, double, float, int, long, short, boolean) and the void type representing no return value are represented by an uppercase character, while the object type is represented by the character L plus object The fully qualified name to indicate, see the following table for details:



For the array type, each dimension will be described by a leading [ character, such as a two-dimensional array defined as java.lang.String[][] type, it will be recorded as: [[Ljava/lang/String; ,, an integer array int[] is recorded as [I.

 When using a descriptor to describe a method, it is described in the order of the parameter list first and then the return value. The parameter list is placed in a set of parentheses "( )" according to the strict order of the parameters. For example, the descriptor of the method java.lang.String toString() is ( ) LJava/lang/String;, and the descriptor of the method int abc(int[] x, int y) is ([II) I.

The object array created as shown in the figure is [L+ fully qualified name + ";"


4.3.3 Constant types and structures


Each item in the constant pool is a table with 14 types of items, as shown in the following table:


The 14 types have different structures, as shown in the table below:

 


According to the description of each type in the above figure, we can also know what each type is used to describe in the constant pool (mainly literals, symbol references). For example:
CONSTANT_Integer_info is used to describe the literal information in the constant pool, and it is only integer literal information.
The constant item types marked 15, 16, and 18 are used to support dynamic language calls (only added in jdk1.7).

Details:

The CONSTANT_Class_info structure is used to represent a class or interface

The CONSTAT_Fieldref_info, CONSTAHT_Methodref_infoF and lCONSTANIT_InterfaceMethodref_info structures represent fields, squares and conventions

The CONSTANT_String_info structure is used to represent a constant object of type String

CONSTANT_Integer_info and CONSTANT_Float_info represent 4-byte (int and float) numeric constants

The CONSTANT_Long_info and CONSTAT_Double_info structures represent 8-character (long and double) numeric constants

In the constant pool table of the class file, all the a-byte constant borrows occupy the space of two table members (items). If a CONSTAHT_Long_info and CNSTAHT_Double_info structure has an index bit n in the constant pool, then an available index bit n+2 in the constant pool, at this time the item with index n+1 in the constant pool length is still valid but must be considered unavailable .
The CONSTANT_NameAndType_info structure is used to represent a field or method, but unlike the previous three structures, the CONSTANT_NameAndType_info structure does not indicate the class or interface to which the field or method belongs.

CONSTANT_Utf8_info is used to represent the value of a character constant

The CONSTANT_MethodHandle_info structure is used to represent the method handle

The CONSTANT_MethodType_info structure represents the method type

The CONSTANT_InvokeDynamic_info structure represents the bootstrap method (bootstrap method) used by the invokedynamic instruction, the dynamic invocation name (dynamic invocation name), parameters and return type used by the bootstrap method, and a series of static arguments (static argument) can be passed to the bootstrap method ) constants.

4.3.4 Interpretation of constants


We divide according to the above type structure table, and determine the following digits according to the first byte of each constant. If it is a string, then the second and third bytes also determine the number of characters, and finally Get 21 constants. Each red tick is an item.


The first item
is the first constant. Let’s see what its flag is. The first value is 0x0a, which is 10. Check the table above to see that the corresponding item type is CONSTANT_Methodref_info, which is the symbolic reference of the method in the class. . Its structure is:


That is, the next 4 bytes are its content, which are two index items:


The value of the first two digits is 0x0004, which is 4, pointing to the index of the fourth item in the constant pool;

 

Item 4
The value of the first byte of item 4 is 0x07. From the above table, we can see that the corresponding item type is CONSTANT_Class_info.


The last two digits of the 21st item
are 0x0015, which is 21, which points to the index of the 21st item in the constant pool. The first digit of the 21st item is 0x01, which shows that it is a string.

 Put it in the tool and you can see that the character length corresponding to the 21st item is 16, which is translated as java/lang/object, which corresponds to the index of the fully qualified name pointed to by the 4th item


Item 18
The last two digits of the first item are 0x0012

 

The value of the last two bits is 0x0012, which is 18, pointing to the index of the 18th item of the constant pool.


The first byte of item 18 is 0x0c, which is 12. There are two fields, one describing the method name and one seckill return value type and formal parameter list. 

 The first byte after that is 0x0007

Item 7

The first byte of the seventh item is 0x01, which is also a string. The length of this string is 6 bytes, which is translated as

Item 8
The second byte is 0x0008, which is item 8


The first byte of item 8 is 0x01, which means it is also a string with a length of 3, which means ()v, and the code has no parameter void method. So far, the interpretation of the first constant has been completed, and the analysis method of the following constants is the same, so it will not be analyzed.

 The right side of the figure below shows the 21 constants decoded in jclasslib


Summary 1
The common point of these 14 tables (or constant item structures) is: the first bit at the beginning of the table is a u1 type flag (tag), which represents which table structure is currently used by this constant item, that is, which constant type.
In the constant pool list, the CONSTANT_Utf8_info constant item is a modified UTF-8 encoding format to store constant string information such as literal strings, fully qualified names of classes or interfaces, simple names of fields or methods, and descriptors. .
Another characteristic of these 14 constant item structures is that the bytes occupied by 13 constant items are fixed, and only the bytes occupied by CONSTANT_Utf8_info are not fixed, and its size is determined by length. why? Because from the content stored in the constant pool, it can be seen that it stores literals and symbol references. In the end, these contents will be a string. The size of these strings is determined when writing a program. For example, if you define a class, the class name can be Take the long and take the short, so the size is not fixed before compilation, after compilation, you can know its length through utf-8 encoding.
Summary 2
Constant pool: It can be understood as the resource warehouse in the Class file. It is the data type most associated with other projects in the Class file structure (many subsequent data types will point here), and it is also the data that occupies the largest space in the Class file. one of the items.
Why should these contents be included in the constant pool? When the Java code is compiled with Javac, there is no "connection" step like C and C++, but a dynamic link is performed when the virtual machine loads the C1ass file. That is to say, the final memory layout information of each method and field will not be saved in the Class file, so if the symbolic references of these fields and methods do not undergo runtime conversion, the real memory entry address cannot be obtained, and it cannot be directly accessed by the virtual machine. use. When the virtual machine is running, it needs to obtain the corresponding symbol reference from the constant pool, and then parse and translate it into a specific memory address when the class is created or run. Regarding the content of class creation and dynamic linking, we will explain in detail during the virtual machine class loading process


5. Access ID


Access flag (access_flag, access flag, access flag)

 After the constant pool, follow the access token. The tag is represented by two bytes and is used to identify some class or interface-level access information, including: whether the Class is a class or an interface; whether it is defined as a public type; whether it is defined as an abstract type; if it is a class, whether it is declared For final and so on. The various access tokens are as follows:


Class access rights are usually constants beginning with ACC_.

Each type of representation is achieved by setting specific bits in the 32 bits of the access flag. For example, if it is a public final class, the mark is ACC_PUBLIC | ACC_FINAL.

Using ACC_SUPER allows the class to more accurately locate the method super.method() of the parent class, and modern compilers will set and use this flag.


The access ID of the above case is 0x0021, which is 0x0001+0x0020

 Supplementary note:

A class file with the ACC_INTERFACE flag represents an interface rather than a class, and vice versa, it represents a class rather than an interface.
If a class file is set with the ACC_INTERFACE flag, then the ACC_ABSTRACT flag must also be set. Also it can no longer set the ACC_FINAL, ACC_SUPER or ACC_ENUM flags.
If the ACC_INTERFACE flag is not set, then this class file can have all other flags in the above table except ACC_ANNOTATION. Of course, except for mutually exclusive flags such as ACC_FINAL and ACC_ABSTRACT. These two flags must not be set at the same time.
The ACC_SUPER flag is used to determine which execution semantics are used by the invokespecial instruction in a class or interface. Compilers targeting the Java virtual machine instruction set should set this flag. For Java SE 8 and subsequent versions, regardless of the actual value of this flag in the class file, and regardless of the version number of the class file, the Java virtual machine considers that each class file has the ACC_SUPER flag set.
The ACC_SUPER flag is designed for backward compatibility with code compiled by older Java compilers. The current ACC_SUPER flag has no definite meaning in the access_flags generated by the compiler before JDK1.0.2. If this flag is set, the 0racle Java virtual machine implementation will ignore it.
The ACC_SYNTHETIC flag means that the class or interface was generated by the compiler, not the source code.
Annotation types must have the ACC_ANNOTATION flag set. If the ACC_ANNOTATION flag is set, the ACC_INTERFACE flag must also be set.
The ACC_ENUM flag indicates that the class or its parent class is an enumeration type.


6. Class index, parent class index, interface index


After the access tag, the category of the class, the parent category and the implemented interface will be specified in the following format:


A class can only inherit single inheritance, but it can implement multiple interfaces, and all interfaces are also in the form of arrays

 These three items of data are used to determine the inheritance relationship of this class:

The class index is used to determine the fully qualified name of this class.
The parent class index is used to determine the fully qualified name of the parent class of this class. Since the Java language does not allow multiple inheritance, there is only one parent class index. Except for java.1ang.Object, all Java classes have parent classes. Therefore, except for java.lang.Object, all Java classes have parent class indexes. Not for e.
The interface index collection is used to describe which interfaces this class implements, and these implemented interfaces will be arranged in the interface index from left to right according to the order of the interfaces after the implements statement (if the class itself is an interface, it should be an extends statement) set.
this_class (class index)
2-byte unsigned integer, pointing to the index of the constant pool. It provides the fully qualified name of the class, such as com/atguigu/java1/Demo. The value of this_class must be a valid index into an entry in the constant pool table. The member of the constant pool at this index must be a CONSTANT_Class_info type structure, which represents the class or interface defined by this class file.

super_class (parent class index)
2-byte unsigned integer, pointing to the index of the constant pool. It provides the fully qualified name of the parent class of the current class. If we do not inherit any class, it inherits the java/lang/object class by default. At the same time, since Java does not support multiple inheritance, there is only one parent class.

The parent class pointed to by super_class cannot be final.

interfaces
points to the constant pool index collection, which provides a symbolic reference to all implemented interfaces

Since a class can implement multiple interfaces, it is necessary to save the indexes of multiple interfaces in the form of an array, indicating that each index of the interface is also a CONSTANT_Class pointing to the constant pool (of course, it must be an interface here, not a class).

Ⅰ. interfaces_count (interface counter)
The value of the interfaces_count item indicates the number of direct superinterfaces of the current class or interface.

Ⅱ. interfaces[] (interface index collection)
The value of each member in interfaces[] must be a valid index value to an item in the constant pool table, and its length is interfaces_count. Each member interfaces[i] must be a CONSTANT_Class_info structure, where 0 <= i < interfaces_count. In interfaces[], the order of interfaces represented by each member is the same as that given in the corresponding source code (from left to right), that is, interfaces[0] corresponds to the leftmost interface in the source code.


They are all indexes pointing to the constant pool. For example, for the first class index 0x0003, go to the third item 0x070014 of the constant pool. 0x0014 is 20, and then look for the 20th item. The translation is the fully qualified name of Demo

 


7. Field table collection


fields
are used to describe variables declared in interfaces or classes. Fields include class-level variables and instance-level variables, but do not include local variables declared inside methods and code blocks.
What is the name of the field and what data type the field is defined as cannot be fixed, and can only be described by referring to constants in the constant pool.
It points to the collection of constant pool indexes, which describe the complete information of each field. For example, the identifier of the field, the access modifier (public, private, or protected), whether it is a class variable or an instance variable (static modifier), whether it is a constant (final modifier), etc.

Precautions:

Fields inherited from parent classes or implemented interfaces will not be listed in the field table collection, but fields that do not exist in the original Java code may be listed. For example, in order to maintain access to the external class in the internal class, a field pointing to the external class instance will be automatically added.
In the Java language, fields cannot be overloaded. Regardless of whether the data types and modifiers of the two fields are the same, they must use different names. But for bytecodes, if the descriptors of the two fields are inconsistent, then Fields with the same name are legal.
fields_counter
fields_count(fields_counter)

The value of fields_count indicates the number of members in the fields table of the current class file. Use two bytes to represent.

Each member in the fields table is a field_info structure, which is used to represent all class fields or instance fields declared by the class or interface, excluding variables declared inside the method, and those fields inherited from the parent class or parent interface .


field table

The field counter in the above figure is 0x0001 and there is only one field

Ⅰ. Field table access identifier
We know that a field can be modified by various keywords, such as: scope modifiers (public, private, protected), static modifiers, final modifiers, volatile modifiers, etc. Therefore, it can be used to mark fields with some flags like the access flags of the class. Field access flags are as follows:

Flag name Flag value Meaning
ACC_PUBLIC 0x0001 Whether the field is public
ACC_PRIVATE 0x0002 Whether the field is private
ACC_PROTECTED 0x0004 Whether the field is protected
ACC_STATIC 0x0008 Whether the field is static ACC_FINAL 0x0010 Whether the
field is final ACC_VOLATILE 0x0040 Whether the
field is volatile
ACC_TRANSTENT 0x0080 Whether the field is transient
ACC_SYNCHETIC 0x1000 Whether it is automatically generated by the compiler
ACC_ENUM 0x4000 Whether the field is enum
Ⅱ. The field name index
0x0005 corresponds to the fifth constant,
which corresponds to utf8 encoding, which translates to num

Ⅲ. Descriptor index
The role of the descriptor is to describe the data type of the field, the parameter list of the method (including quantity, type and order) and the return value. According to the descriptor rules, the basic data types (byte, char, double, float, int, long, short, boolean) and the void type representing no return value are represented by an uppercase character, while the object is represented by the character L plus the object fully qualified name, as follows:


Ⅳ. Attribute table set
The value in the above figure is 0x0000, which means no, and the following fields are over. Add final constants to have initialization information


A field may also have some attributes for storing more additional information. Such as initialization value, some annotation information, etc. The number of attributes is stored in attribute_count, and the specific content of attributes is stored in the attributes array.

// Take constant attributes as an example, the structure is:

Description: For constant attributes, the value of attribute_length is always 2.

 8. Method table collection


methods: Points to a constant pool index collection, which fully describes the signature of each method.

In the bytecode file, each method_info item corresponds to the method information in a class or interface. For example, the access modifier of the method (public, private or protected), the return value type of the method, and the parameter information of the method.
If the method is not abstract or not native, it will be reflected in the bytecode.
On the one hand, the methods table only describes methods declared in the current class or interface, not including methods inherited from parent classes or parent interfaces. On the other hand, the methods table may have methods automatically added by the compiler, the most typical is the method information generated by the compiler (for example: class (interface) initialization method () and instance initialization method ()).
Precautions for use:
In the Java language, to overload a method, in addition to having the same simple name as the original method, it is also required to have a different signature from the original method, and the signature is a method. The set of field symbol references of each parameter in the constant pool, that is, because the return value will not be included in the feature signature, it is impossible to overload an existing method in the Java language only by relying on the difference in the return value. But in the Class file format, the scope of the feature signature is larger, as long as the descriptors are not exactly the same, the two methods can coexist. In other words, if two methods have the same name and signature, but return different values, they can legally coexist in the same class file.

That is to say, although the Java syntax specification does not allow multiple methods with the same signature to be declared in a class or interface, contrary to the Java syntax specification, the bytecode file just allows storing multiple methods with the same signature. The only condition is that the return values ​​between these methods cannot be the same.


method counter
methods_count(method counter)

The value of methods_count indicates the number of members in the methods table of the current class file. Use two bytes to represent.

Each member of the methods table is a method_info structure.

Method table
Each member in the methods table must be a method_info structure, which is used to represent a complete description of a method in the current class or interface. If the access_flags item of a method_info structure has neither the ACC_NATIVE flag nor the ACC_ABSTRACT flag set, then the structure should also contain the Java virtual machine instructions used to implement this method.

The method_info structure can represent all methods defined in classes and interfaces, including instance methods, class methods, instance initialization methods, and class or interface initialization methods

The structure of the method table is actually the same as that of the field table. The structure of the method table is as follows:


Ⅰ. Method table access flag
Like the field table, the method table also has access flags, and some of their flags are the same, and some are different. The specific access flags of the method table are as follows:

 Ⅱ. Method name index
is similar to field name index

Ⅲ. Descriptor index
Similar to field description index

9. Property sheet collection


The value of the attribute counter
attributes_count indicates the number of members in the attribute table of the current class file. Each item in the attribute table is an attribute_info structure.

attribute table
attributes[] (attribute table)

The value of each item of the attribute table must be an attribute_info structure. The structure of the attribute table is relatively flexible. Various attributes only need to meet the following structure. Each attribute table must follow the following structure, and each attribute table is followed by its own attribute structure.

Common format for attributes


attribute type 

Attribute tables can actually have many types, and the Code attribute seen above is just one of them. There are 23 attributes defined in Java8. The following properties are predefined in a virtual machine:


Or (check the official website)

 

 Detailed explanation of some attributes

① ConstantValue property

The ConstantValue property represents the value of a constant field. Located in the attribute table of the field_info structure.


② Deprecated attribute


③ Code attribute

 The Code attribute is to store the code in the method body. However, not all method tables have a Code attribute. Like interfaces or abstract methods, they do not have a specific method body, so there will be no Code attribute. The structure of the Code attribute table is as follows:


It can be seen that the first two items of the Code attribute table are consistent with the attribute table, that is, the Code attribute table follows the structure of the attribute table, and the latter ones are his custom structures.

 ④ InnerClasses property

For the convenience of description, a Class format representing a class or interface is specially defined as C. If C's constant pool contains a CONSTANT_Class_info member, and the class or interface represented by this member does not belong to any package, then the attribute table of C's ClassFile structure must contain the corresponding InnerClasses attribute. The InnerClasses attribute was introduced in JDK1.1 to support inner classes and inner interfaces, and is located in the attribute table of the ClassFile structure.

⑤ LineNumberTable property

The LineNumberTable attribute is an optional variable-length attribute located in the attribute table of the Code structure.

The LineNumberTable attribute is used to describe the correspondence between Java source code line numbers and byte code line numbers. This property can be used to locate the line of code execution when debugging.

start_pc, that is, the bytecode line number; line_number, that is, the Java source code line number.
In the attribute table of the Code attribute, the LineNumberTable attribute can appear in any order. In addition, multiple LineNumberTable attributes can jointly represent the content represented by a line number in the source file, that is, the LineNumberTable attribute does not need to correspond to the lines of the source file.


⑥LocalVariableTable property

 LocalVariableTable is an optional variable-length attribute located in the attribute table of the Code attribute. It is used by debuggers to determine information about local variables during method execution. In the attribute table of the Code attribute, the LocalVariableTable attribute can appear in any order. Each local variable in the Code attribute can have at most one LocalVariableTable attribute.

start pc + length indicates the offset position of the start and end of the life cycle of this variable in the bytecode (this life cycle is from the beginning e to the end 10) index
is the slot of this variable in the local variable table (the slot can be reset Use)
name is the variable name
Descriptor indicates the local variable type description

⑦ Signature attribute

 The Signature attribute is an optional fixed-length attribute located in the attribute table of the ClassFile, field_info or method_info structure. In the Java language, if the generic signature of any class, interface, initialization method or member contains type variables (Type Variables) or parameterized types (Parameterized Types), the Signature attribute will record generic signature information for it.

⑧ SourceFile property

SourceFile attribute structure


As you can see, its length is always fixed at 8 bytes.
Why is the length of attribute_length 2? The official website explains that it must be 2

 ⑨ Other properties

There are more than 20 predefined attributes in the Java virtual machine, so I won’t introduce them one by one here. Through the introduction of the above attributes, as long as you understand the essence, the interpretation of other attributes is also easy.

Case Analysis
It can be seen from the bytecode that the attribute name index is two bytes 0x0009, which corresponds to code, so the following bytes are the structure of the code attribute


The structure of the code attribute table

 

 The attribute name is 0x0009, corresponding to the code
attribute length 0x00000038, which corresponds to 54 bytes, so the first red 0x00 is the code attribute. The
maximum depth of the operand stack is 0x0002, which corresponds to
the storage space required for 2 local variable tables 0x0001, which corresponds to The instruction length of 1
byte code is 0x0000000a, corresponding to 10 bytes, but there are only 6 instructions according to jclasslib


Analyze line by line, click into the official document corresponding to the first instruction, you can see that aload_0 corresponds to 0x2a, which just corresponds to the first byte, and so on, the second instruction corresponds to 0xb7, and in the second instruction invokespecial Finally, #1 corresponds to a constant pool index 0x0001, which we analyzed above just corresponds to java/lang/Object, so #2 below is also two bytes corresponding to an index, which is exactly 10 bytes in length.


The attribute counter is 2, and the method has two attributes, **LineNumberTable and LocalVariableTable**


They all follow the format of the attribute

line_number_table_length为2

 The second one is LocalVariableTable

The last line is the sourcefile attribute, which also follows the attribute format

Guess you like

Origin blog.csdn.net/s_nshine/article/details/132104410