We know that Java’s most famous slogan is “Write Once, Run Anywhere,” and its platform-independence is dependent on the JVM. All Java files are compiled into bytecode files, and the virtual machine only needs to know bytecode files. This is an essential part of understanding virtual machines and the class loading mechanism.
A Class file is a set of 8-byte binary streams in which all data is arranged without spacing. Multi-byte data is stored in a big-endian order. The Class file stores data structures in a pseudo-code form that is close to the structures in C, and contains only unsigned and table data structures:
- Unsigned numbers :u1, U2, U4, u8 table 1, 2, 4, 8 byte unsigned numbers respectively
- Table: A compound data type consisting of unsigned numbers or other tables. The Class file is itself a table.
Class table structure:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}Copy the code
Referring to the data structure above, the Class file consists of 10 parts: 1. Magic number 2. Primary and secondary versions of Class files 3. Constant pool 4. Access flag 5. Current class name 6. Parent class name 7. Inherited interface name 8. Number of fields included + number of fields 9. Number of methods included + method 10. The number of all attributes contained + attributes
Let’s analyze each part in turn:
1. The magic number
The Magic number is used to determine the type of file. This is the Class file that checks whether the file is acceptable to the virtual machine. Many files use magic numbers to determine file types, not extensions (which can be changed at will). See my in-depth understanding of program construction (I).
The magic number of the Class file is “0xcafebabe”, coffee babe? Java itself is also a kind of Java coffee. Here I also write a small test program, to see its binary stream:
package com.shuqing28;
public class TestClass {
private int m;
public int inc() {
returnm+1; }}Copy the code
We compiled to a.class file using javac, which can be opened with WinHex on Windows or hexdump on Linux, using the following command:
$ hexdump -C TestClass.class 00000000 ca fe ba be 00 00 00 34 00 16 0a 00 04 00 12 09 |....... 4... | 00000010 00 03 00 13 07 00 14 07 00 15 01 00 01 6d 01 00 |............. m.. | 00000020 01 49 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29 |.I... <init>... ()| 00000030 56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e |V... Code... LineN| 00000040 75 6d 62 65 72 54 61 62 6c 65 01 00 12 4c 6f 63 |umberTable... Loc| 00000050 61 6c 56 61 72 69 61 62 6c 65 54 61 62 6c 65 01 |alVariableTable.| 00000060 00 04 74 68 69 73 01 00 19 4c 63 6f 6d 2f 73 68 |.. this... Lcom/sh| 00000070 75 71 69 6e 67 32 38 2f 54 65 73 74 43 6c 61 73 |uqing28/TestClas| 00000080 73 3b 01 00 03 69 6e 63 01 00 03 28 29 49 01 00 |s; . inc... ()I.. | 00000090 0a 53 6f 75 72 63 65 46 69 6c 65 01 00 0e 54 65 |.SourceFile... Te| 000000a0 73 74 43 6c 61 73 73 2e 6a 61 76 61 0c 00 07 00 |stClass.java.... | 000000b0 08 0c 00 05 00 06 01 00 17 63 6f 6d 2f 73 68 75 |......... com/shu| 000000c0 71 69 6e 67 32 38 2f 54 65 73 74 43 6c 61 73 73 |qing28/TestClass| 000000d0 01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a |... java/lang/Obj| 000000e0 65 63 74 00 21 00 03 00 04 00 00 00 01 00 02 00 |ect.! . | 000000f0 05 00 06 00 00 00 02 00 01 00 07 00 08 00 01 00 |................ | 00000100 09 00 00 00 2f 00 01 00 01 00 00 00 05 2a b7 00 |.... /... *.. | 00000110 01 b1 00 00 00 02 00 0a 00 00 00 06 00 01 00 00 |................ | 00000120 00 03 00 0b 00 00 00 0c 00 01 00 00 00 05 00 0c |................ | 00000130 00 0d 00 00 00 01 00 0e 00 0f 00 01 00 09 00 00 |................ | 00000140 00 31 00 02 00 01 00 00 00 07 2a b4 00 02 04 60 |.1........ *... `| 00000150 ac 00 00 00 02 00 0a 00 00 00 06 00 01 00 00 00 |................ | 00000160 06 00 0b 00 00 00 0c 00 01 00 00 00 07 00 0c 00 |................ | 00000170 0d 00 00 00 01 00 10 00 00 00 02 00 11 |............. | 0000017dCopy the code
See the first four bytes on the first line are 0xcafebabe in hexadecimal, so the file type is indeed a.class file.
2. The version number
Bytes 5 and 6 are Minor versions, and bytes 7 and 8 are Major versions. Our major version number is 0x0034 (52).
JDK 1.6 =50 JDK 1.5 = 49 JDK 1.4 = 48 JDK 1.3 = 47 JDK 1.2 = 46 JDK 1.1 = 45
You can see that I’m using Java 8-compiled code.
3. The constant pool
Let’s continue with the first line of the binary:
00000000 ca fe ba be 00 00 00 34 00 16 0a 00 04 00 12 09 |....... 4... |Copy the code
After the major version number 0x0034 is 0x0016, which represents the capacity of the constant pool. A constant pool can be thought of as a resource repository for Class files. The data structure contained in the constant pool looks like this:
cp_info {
u1 tag;
u1 info[];
}Copy the code
Each item in the constant pool contains a cp_INFO object starting with a tag that represents the constant type, and info has its own structure depending on the type. There are currently 14 constant types:
Constant Type | Value |
---|---|
CONSTANT_Class | 7 |
CONSTANT_Fieldref | 9 |
CONSTANT_Methodref | 10 |
CONSTANT_InterfaceMethodref | 11 |
CONSTANT_String | 8 |
CONSTANT_Integer | 3 |
CONSTANT_Float | 4 |
CONSTANT_Long | 5 |
CONSTANT_Double | 6 |
CONSTANT_NameAndType | 12 |
CONSTANT_Utf8 | 1 |
CONSTANT_MethodHandle | 15 |
CONSTANT_MethodType | 16 |
CONSTANT_InvokeDynamic | 18 |
The above 0x0016 translates to 22 in decimal, so there are 21 constants in the constant pool. Since the index in the constant pool is counted from 1, the constant indexes range from 1 to 21.
00000000 ca fe ba be 00 00 00 34 00 16 0a 00 04 00 12 09 |....... 4... |Copy the code
CONSTANT_Methodref (tag = 0x0a, tag = 0x0a); Here you can refer to The official Oracle document The Class File Format.
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}Copy the code
Since.class files are unspaced binaries, continue reading:
- tag:
0x0a
CONSTANT_Methodref, as mentioned above - Class_index: points to a constant of type CONSTANT_Class_info in the constant pool, representing the name of the method above
- Name_and_type_index: refers to the CONSTANT_NameAndType_info constant in the constant pool and is a description of the method
Since class_index is two bytes, 0x0004, or 4, points to the fourth constant in the constant pool, and name_AND_type_index is 0x0012, which points to the 18th constant. Constants 4 and 18 will be analyzed later.
Read on until you get to the end of the first line, which is 0x09, indicating CONSTANT_Fieldref, which indicates the following definition of a field, in the official documentation, in the format:
CONSTANT_Fieldref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}Copy the code
The structure is the same as CONSTANT_Methodref_info, at which point the second line is read:
00000010 00 03 00 13 07 00 14 07 00 15 01 00 01 6d 01 00 |............. m.. |Copy the code
Class_index is 0x0003, pointing to the third constant, and name_AND_type_index is 0x0013, pointing to the 13th constant. At this point, I continue reading until I reach the third constant. A constant of this type represents a symbolic reference to a class or interface. The structure of the CONSTANT_Class is as follows:
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}Copy the code
Tag is 7, name_index is 0x0014, and decimal is 20, pointing to the 20th constant, so we’ve read many bytes. However, it is very tiring to parse. Fortunately, Java comes with javap tools that can help us analyze the content of bytecode. Execute the following statement:
javap -verbose TestClass.classCopy the code
We can get:
Last modified Nov 14, 2017; size 381 bytes
MD5 checksum 102d643185c4823ef103931ff3e34462
Compiled from "TestClass.java"
public class com.shuqing28.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#18 // java/lang/Object."
":()V
#2 = Fieldref #3.#19 // com/shuqing28/TestClass.m:I
#3 = Class #20 // com/shuqing28/TestClass
#4 = Class #21 // java/lang/Object
#5 = Utf8 m
#6 = Utf8 I
#7 = Utf8
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/shuqing28/TestClass;
#14 = Utf8 inc
#15 = Utf8 ()I
#16 = Utf8 SourceFile
#17 = Utf8 TestClass.java
#18 = NameAndType #7:#8 // "
":()V
#19 = NameAndType #5:#6 // m:I
#20 = Utf8 com/shuqing28/TestClass
#21 = Utf8 java/lang/Object{ public com.shuqing28.TestClass(); descriptor: ()V flags: ACC_PUBLIC ... / / to omitCopy the code
Constant pool = Methodref (Methodref); class_index (Methodref); CONSTANT_Class (Methodref); Name_index is a constant of type CONSTANT_Utf8. Name_index is a constant of type CONSTANT_Utf8.
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}Copy the code
The first tag is 1, length indicates the length of the character array, and bytes[length] is a utF-8 encoded string that resolves to com/ shuqing28/testClass, the fully qualified name of the class.
Continuing back to the first Methodref constant, whose name_AND_type_index value is 18, continue to find the 18th constant, which is of type CONSTANT_NameAndType_info and represents information about a method:
CONSTANT_NameAndType_info {
u1 tag;
u2 name_index;
u2 descriptor_index;
}Copy the code
Name_index refers to the constant 7, #7 = Utf8
, is a CONSTANT_Utf8_info type, and its value is, this is the method name, descriptor_index refers to the constant 8, #8 = Utf8 ()V, is the description of the method, What this expression means will be explained below. So we can analyze all 21 constants one by one.
The Class file starts with a list of constants, followed by indexes that refer to constants in the previous constant pool to describe the entire Class definition. Just like we have a dictionary, we use the words in the dictionary to make our sentences, but the Class file has strict formatting rules, and the following content basically describes the contents of a Class in a fixed format, without spacing.
4. Access flags
The next two bytes after the constant pool end represent access_flags, which are used to identify access information about a Class or interface, including whether the Class is a Class or an interface, public, abstract, and final. The meanings of access tags are as follows:
Sign the name | Flag values | meaning |
---|---|---|
ACC_PUBLIC | 0x0001 | Declared public; may be accessed from outside its package. |
ACC_FINAL | 0x0010 | Declared final; no subclasses allowed. |
ACC_SUPER | 0x0020 | Treat superclass methods specially when invoked by the invokespecial instruction. |
ACC_INTERFACE | 0x0200 | Is an interface, not a class. |
ACC_ABSTRACT | 0x0400 | Declared abstract; must not be instantiated. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |
ACC_ENUM | 0x4000 | Declared as an enum type. |
TestClass is of type public and compiled with a compiler later than JDK1.2 (this value is true for all compiler later than JDK1.2). All flags are false. So access_flags values should be: 0 x0001 x0021 | 0 x0020 = 0. We find the last line of the constant pool:
000000e0 65 63 74 00 21 00 03 00 04 00 00 00 01 00 02 00 |ect.! . |Copy the code
65, 63, 74 correspond to ECT respectively, followed by 0x0021, which is consistent with our analysis results.
5. Class index, parent index, and interface index collection
Referring to the data structure of the ClassFile at the beginning of this article, these three are defined as:
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];Copy the code
Both the class index and the superclass index are u2-type data, whereas the interface index gives the number of interfaces first, followed by an array of interfaces. These three values reveal the inheritance of a class.
000000e0 65 63 74 00 21 00 03 00 04 00 00 00 01 00 02 00 |ect.! . |Copy the code
#3 = Class #20 // com/ shuqing28/testclass #3 = Class #20 // com/ shuqing28/testclass The 20th constant is a CONSTANT_Utf8 variable with a value of com/ shuqing28/testclass, which represents the fully qualified name string of the class. #4 = Class #21 // Java /lang/Object and #21 // Java /lang/Object. Object is the parent of all classes. Next is 0x0000, so TestClass does not implement any interface.
6. Set of field tables
Field tables are used to describe variables declared in interfaces or classes. Fields include class-level variables as well as instance-level variables, but do not include local variables within methods. A Java field can include information about the field’s scope, whether it is an instance variable or a class variable, whether it is final, whether it is concurrently visible (volatile), whether it can be serialized (transient), and the field data type. The following is the specific structure of the field table:
field_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}Copy the code
Access_flags can take the following values:
Sign the name | Flag values | meaning |
---|---|---|
ACC_PUBLIC | 0x0001 | Declared public; may be accessed from outside its package. |
ACC_PRIVATE | 0x0002 | Declared private; usable only within the defining class. |
ACC_PROTECTED | 0x0004 | Declared protected; may be accessed within subclasses. |
ACC_STATIC | 0x0008 | Declared static. |
ACC_FINAL | 0x0010 | Declared final; never directly assigned to after object construction (JLS §17.5). |
ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached. |
ACC_TRANSIENT | 0x0080 | Declared transient; not written or read by a persistent object manager. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
ACC_ENUM | 0x4000 | Declared as an element of an enum. |
Generally speaking, only one ACC_PUBLIC, ACC_PRIVATE, and ACC_PROTECTED flag can exist at most. The other flags are based on the nature of Java language itself.
After the access_flags flag are the two index values name_index and Descriptor_index, both indexes to the constant pool, representing the simple name of the field and the field and method descriptors, respectively.
Fully qualified names: the previously mentioned com/ shuqing28/testclass is a fully qualified name, which replaces all “.” in Java code with “/”, usually using “;”. At the end. Simple name: The name of a method or field without type or modifier, such as “inc” and “m” in the code above. A method descriptor describes the data type, the method’s argument list, and the return value. We know that in C++ when we overload a function, we actually change the name of the function to include arguments to the function, such as add(int x, int y), which might be Add_Int_Int when compiled, but in Java we use an uppercase character for basic data types, Object classes are represented by fully qualified names of L+ objects.
Description Identifier character meaning:
Identification character | meaning |
---|---|
B | byte |
C | char |
D | double |
F | float |
I | int |
J | long |
S | short |
Z | boolean |
V | void |
L | Object, such as Ljava/lang/Object |
[[Java /lang/String, int[] is recorded as [I. When describing methods with descriptors, they are described in the order of the returned values in the argument list, which also needs to be enclosed in parentheses. For example, the “() V” mentioned above represents a method with an empty argument and a return value of void, i.e. the void inc() method in the code.
To do a more complicated one, int indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, Int fromIndex), whose descriptor is ([CII[CIII) I.
Continuing with the binary code of the program we mentioned earlier:
000000e0 65 63 74 00 21 00 03 00 04 00 00 00 01 00 02 00 |ect.! . | 000000f0 05 00 06 00 00 00 02 00 01 00 07 00 08 00 01 00 |................ |Copy the code
In the previous section, we looked at 0x0000 in the first line, and then 0x01. This value actually represents the number of fields in the table. Our code contains only one field. #5 = Utf8 m, then descriptor_index (0x0006), access_private (0x0002), ACC_PRIVATE (#5 = Utf8 m), then descriptor_index (0x0006), #6 = Utf8 I private int m;
Generally, after decriptor_index, there is a set of attributes to store some additional information, with 0x0000 representing no attribute fields. Private static int m = 123; You may have a ConstantValue attribute that points to the ConstantValue 123.
7. Method table collection
The method table collection is very similar to the field table collection, with the same structure:
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}Copy the code
There are just different options for accessing flags and property sheet collections. For example, access_flags has the following optional values:
Sign the name | Flag values | meaning |
---|---|---|
ACC_PUBLIC | 0x0001 | Declared public ; may be accessed from outside its package. |
ACC_PRIVATE | 0x0002 | Declaredprivate ; accessible only within the defining class. |
ACC_PROTECTED | 0x0004 | Declaredprotected ; may be accessed within subclasses. |
ACC_STATIC | 0x0008 | Declaredstatic . |
ACC_FINAL | 0x0010 | Declaredfinal ; must not be overridden |
ACC_SYNCHRONIZED | 0x0020 | Declaredsynchronized ; invocation is wrapped by a monitor use. |
ACC_BRIDGE | 0x0040 | A bridge method, generated by the compiler. |
ACC_VARARGS | 0x0080 | Declared with variable number of arguments. |
ACC_NATIVE | 0x0100 | Declarednative ; implemented in a language other than Java. |
ACC_ABSTRACT | 0x0400 | Declaredabstract ; no implementation is provided. |
ACC_STRICT | 0x0800 | Declaredstrictfp ; floating-point mode is FP-strict. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
As you can see, Methods such as ACC_SYNCHRONIZED,ACC_NATIVE,ACC_STRICT and ACC_ABSTRACT are added, corresponding to synchronized, native, strictFP and abstract, which can only modify methods.
Now we can continue to analyze the binary code of our program.
000000f0 05 00 06 00 00 00 02 00 01 00 07 00 08 00 01 00 |................ | 00000100 09 00 00 00 2f 00 01 00 01 00 00 00 05 2a b7 00 |.... /... *.. |Copy the code
In the previous section we just parsed 0x0000 on line 000000f0, followed by 0x0002, which means there are two methods, and the next few bytes are
0x0001
The access tag is ACC_PUBLIC0x0007
The: name index points to the 7th constant:0x0008
The: descriptor index points to the eighth constant: ()V0x0001
The: property has one0x0009
The: property points to the ninth constant, Code
Now that we have the method definition, where is the method body? The answer is the last Code analyzed above. The next section looks at the various possibilities for property sheet collections.
8. Property sheet collection
Attribute_info has been mentioned several times before. Class files, field tables, and method tables can all carry their own set of attribute_info tables to describe information transferred from certain scenarios. Property lists are not strictly ordered, and any compiler implementing them can add their own property information as long as they do not duplicate existing property names. Here are some of the predefined properties:
The attribute name | Use location | meaning |
---|---|---|
SourceFile | ClassFile | Record the name of the source file |
InnerClasses | ClassFile | Inner class list |
EnclosingMethod | ClassFile | Inner classes have this property, which identifies the enclosing method of the class |
SourceDebugExtension | ClassFile | Used to store additional debugging information. New in JDK1.6 |
BootstrapMethods | ClassFile | Bootstrap method qualifier for storing invokeddynamic instruction references, new in JDK1.7 |
ConstantValue | field_info | Constant value defined by the final keyword |
Code | method_info | Bytecode instructions compiled into Java code |
Exceptions | method_info | Method throws an exception |
RuntimeVisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations | method_info | Specifying which parameters are and are not visible at runtime is new in JDK1.5 |
AnnotationDefault | method_info | Record the default value of the annotation class element, new in JDK1.5 |
MethodParameters | method_info | Logging method parameter information, such as their name, access level, new in JDK1.8 |
Synthetic | ClassFile, field_info, method_info | Presentation methods or fields are automatically generated by the compiler |
Deprecated | ClassFile, field_info, method_info | Field declared as deprecated |
Signature | ClassFile, field_info, method_info | In the Java language, the Signature attribute records generic Signature information for any class, interface, initializer, or member whose generic Signature contains a type variable or parameterized type. Because Java generics are implemented by erasure, this property is required to record relevant information in the generics to avoid signature confusion when type information is erased. JDK1.5 new in |
RuntimeVisibleAnnotations, RuntimeInvisibleAnnotations | ClassFile, field_info, method_info | Support for dynamic annotations, indicating which annotations are and are not visible at runtime, is new in JDK1.5 |
LineNumberTable | Code | The mapping of Java source line numbers to bytecode instructions |
LocalVariableTable | Code | Method local variable description |
LocalVariableTypeTable | Code | The use of characteristic signatures instead of descriptors was added in JDK1.5 to describe generic parameterized types after the introduction of generic syntax |
StackMapTable | Code | A new Type Checker for checking and processing whether the local variables of a target method match the types required by the operation stack |
RuntimeVisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations | ClassFile, field_info, method_info, Code | Records the visibility of annotations on runtime types, including the visibility of annotations on runtime type parameters |
Here are some of the more important attributes:
Code attributes
Let’s start with the structure of the Code attribute:
Code_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
{ u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}Copy the code
- Attribute_name_index: two bytes, pointing to the constant CONSTANT_Utf8_info, the name of the attribute, which is always “Code”.
- Attribute_length: Indicates the length of the attribute value. Since attribute_name_index and attribute_length are 6 bytes, attribute_length is the length of the attribute list minus 6 bytes
- Max_statck: The maximum depth of the operand stack that cannot be exceeded during method execution
- max_locals: Storage space required by local variables. Max_locals unit is Slot, Slot is the smallest unit of virtual machine to a local variable distribution, for byte, char, and float, int, short, such as Boolean and returnAddress length less than 32-bit data types, occupies only a Slot, Data of 64 bytes, such as double and long, need to occupy two slots. Method parameters (including hidden
this
), exception handler parameters and local variables defined by the method body need to be stored in the local variable table. However, max_locals is not the sum of slots occupied by all local variables, because slots can be reused. When a variable goes out of scope, the slot is used by other local variables, and the compiler calculates max_locals based on the scope. - Code_length: Length of bytecode compiled by the compiler
- code: A series of bytes used to store the bytecode instruction, each instruction is a type of u1 single-byte, when the virtual machine to read the bytes, you can know what instruction, know what is the instruction, knew instruction operands are needed, it is ok to continue to read, here is similar to the assembly, the scope of u1 is 0 ~ 255, can express 256 instructions. The Java Virtual Machine specification defines about 200 Instructions. See Instructions. I will write a blog about this later.
- Exception_table_length: Specifies the length of the exception table
- Exception_table: The exception table is not required for Code to exist, so the above length can also be 0. The exception table has four attributes, representing that if an exception of type catch_type occurs between start_PC and end_PC, it will jump to the line pointed to by handler_PC for processing.
Exceptions properties
The Exceptions attribute is at the same level as the Code attribute in the method table. Notice that unlike the Code table above, the Exceptions attribute lists the Exceptions that the method may throw. The structure of the Exceptions attribute table is:
Exceptions_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_exceptions;
u2 exception_index_table[number_of_exceptions];
}Copy the code
- Number_of_exceptions: Number of possible exceptions that can be thrown
- Exception_index_table: Points to the index CONSTANT_Class_info in the constant pool
LineNumberTable properties
LineNumber is used to record the mapping between Java source code and bytecode line numbers. We can also use -g: None or -g: line to ungenerate this property when compiling code, but we can’t see line numbers or break points when debugging code.
The data structure of LineNumberTable is as follows:
LineNumberTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 line_number_table_length;
{ u2 start_pc;
u2 line_number;
} line_number_table[line_number_table_length];
}Copy the code
Let’s look at line_number_table, start_PC is the bytecode line number, and line_number is the Java source line number.
LocalVariableTable properties
The LocalVariableTable attribute is used to describe the relationship between variables in the LocalVariableTable in the stack frame and variables defined in the Java source code. We can also use -g: none or -g: Vars to ungenerate this attribute, but if it is cancelled, the IDE will replace the parameter names with arguments such as arg0 and arg1, resulting in unclear debugging. The data structure of LocalVariableTable is as follows:
LocalVariableTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 local_variable_table_length;
{ u2 start_pc;
u2 length;
u2 name_index;
u2 descriptor_index;
u2 index;
} local_variable_table[local_variable_table_length];
}Copy the code
Local_variable_table local_variable_table
- Start_pc and length: represent the bytecode offset at the beginning of the life cycle of this local variable and the length of scope coverage, respectively
- Name_index and Descriptor_index: Points to constants representing local variable names and local variable descriptors, respectively
- Index: indicates the slot position of the local variable in the local variable table. If the variable is of type double or long, the two slots are index and index+1.
ConstantValue properties
ConstantValue is a fixed-length property that informs the VM to assign a static variable value if int x=3 is also defined. And the static int y = 3; For x, the assignment is done in the instance constructor
, while for static variables, the assignment is done in the class constructor
method or using the ConstantValue property. The current rule of the Javac compiler is that if there are both final and static modifiers, the ConstantValue property is used, which is initialized in < Clinit > when there is only static and the variable type is primitive or String.
InnerClasses attribute
If an inner class is defined in a class, the InnerClasses attribute is used to record the relationship between the inner class and the host. The data structure for InnerClasses is as follows:
InnerClasses_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_classes; // Record how many inner classes {u2 inner_class_info_index; u2 outer_class_info_index; u2 inner_name_index; u2 inner_class_access_flags; } classes[number_of_classes]; }Copy the code
Outer_class_info_index points to the symbolic reference of the host class. Inner_name_index points to the name of the inner class, or 0 if it’s an anonymous inner class. Inner_class_access_flags is the access flag for the inner class, as shown in the following table:
Sign the name | Flag values | meaning |
---|---|---|
ACC_PUBLIC | 0x0001 | Marked or implicitly public in source. |
ACC_PRIVATE | 0x0002 | Marked private in source. |
ACC_PROTECTED | 0x0004 | Marked protected in source. |
ACC_STATIC | 0x0008 | Marked or implicitly static in source. |
ACC_FINAL | 0x0010 | Marked final in source. |
ACC_INTERFACE | 0x0200 | Was an interface in source. |
ACC_ABSTRACT | 0x0400 | Marked or implicitly abstract in source. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |
ACC_ENUM | 0x4000 | Declared as an enum type. |
There are other attributes that you can see in Resources if you want to know more about them.
References:
- Java Virtual Machine Specification
- Java Virtual Machine: Advanced JVM features and best practices