Foreword
With the continuous development of the Java language, Java application scenarios are slowly expanding variety of elegant problem-solving technique has also been derived, such as AOP technology, a clear understanding of the Java Runtime principle becomes necessary, the focus of this article to explain Java bytecode knowledge.
Base bytecodes
Java files generated by the compiler class bytecode files, bytecode file also has its own file format, not to proceed here in detail, look directly through Java tools to bring their own. First, we test class file as follows:
public class Person {
public String name;
public int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
复制代码
Defines a Person class, which has the properties name and age, the compiler generates Person.class file directly using the Java class file this tool dump, dump command is as follows:
javap -v -p Person.class
复制代码
dump generated as follows:
public class com.sec.resourceparse.Person
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #5.#27 // java/lang/Object."<init>":()V
#2 = Fieldref #4.#28 // com/sec/resourceparse/Person.name:Ljava/lang/String;
#3 = Fieldref #4.#29 // com/sec/resourceparse/Person.age:I
#4 = Class #30 // com/sec/resourceparse/Person
#5 = Class #31 // java/lang/Object
#6 = Utf8 name
#7 = Utf8 Ljava/lang/String;
#8 = Utf8 age
#9 = Utf8 I
#10 = Utf8 <init>
#11 = Utf8 ()V
#12 = Utf8 Code
#13 = Utf8 LineNumberTable
#14 = Utf8 LocalVariableTable
#15 = Utf8 this
#16 = Utf8 Lcom/sec/resourceparse/Person;
#17 = Utf8 getName
#18 = Utf8 ()Ljava/lang/String;
#19 = Utf8 setName
#20 = Utf8 (Ljava/lang/String;)V
#21 = Utf8 getAge
#22 = Utf8 ()I
#23 = Utf8 setAge
#24 = Utf8 (I)V
#25 = Utf8 SourceFile
#26 = Utf8 Person.java
#27 = NameAndType #10:#11 // "<init>":()V
#28 = NameAndType #6:#7 // name:Ljava/lang/String;
#29 = NameAndType #8:#9 // age:I
#30 = Utf8 com/sec/resourceparse/Person
#31 = Utf8 java/lang/Object
{
public java.lang.String name;
descriptor: Ljava/lang/String;
flags: ACC_PUBLIC
public int age;
descriptor: I
flags: ACC_PUBLIC
public com.sec.resourceparse.Person();
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 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sec/resourceparse/Person;
public java.lang.String getName();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field name:Ljava/lang/String;
4: areturn
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sec/resourceparse/Person;
public void setName(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: putfield #2 // Field name:Ljava/lang/String;
5: return
LineNumberTable:
line 13: 0
line 14: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/sec/resourceparse/Person;
0 6 1 name Ljava/lang/String;
复制代码
Here intercepted part, briefly look at first is the introduction of such information:
public class com.sec.resourceparse.Person
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
复制代码
Class names, JDK version of the compiler, as well as access modifier
then the string pool:
Constant pool:
#1 = Methodref #5.#27 // java/lang/Object."<init>":()V
#2 = Fieldref #4.#28 // com/sec/resourceparse/Person.name:Ljava/lang/String;
#3 = Fieldref #4.#29 // com/sec/resourceparse/Person.age:I
#4 = Class #30 // com/sec/resourceparse/Person
#5 = Class #31 // java/lang/Object
#6 = Utf8 name
#7 = Utf8 Ljava/lang/String;
复制代码
Here the entire class containing the string inside, contains a declaration of the class information, attribute, etc.
Finally, the method of information:
public java.lang.String getName();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field name:Ljava/lang/String;
4: areturn
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sec/resourceparse/Person;
复制代码
Here is the main method name, access modifiers, flow of information and operational execution stack
after reading the entire class of class files, here are the basics of the bytecode related.
Access modifier
Above the bytecode classes, properties, and methods in both flag information, this is the modifier, and the corresponding value in the access modifiers bytecode classes are as follows:
Identifier name | Identifier value | DEFINITIONS |
---|---|---|
ACC_PUBLIC | 0x0001 | Public Type |
ACC_FINAL | 0x0010 | Final type |
ACC_SUPER | 0x0020 | Allow the use of new bytecode instructions invokespecial semantics |
ACC_INTERFACE | 0x0200 | Interface Modifier |
ACC_ABSTRACT | 0x0400 | abstract modifier |
ACC_SYNTHETIC | 0x1000 | This flag is not generated by user code class |
ACC_ANNOTATION | 0x2000 | Notes modifier |
**ACC_ENUM | 0x400 | Enum modifier |
Described above is a class access modifier, it is also similar to the properties, and methods, but is relatively simple, here is not to continue the.
Type table
In JAVA basic types, arrays, and an object, the bytecode differentiated type of said table as follows:
Types of | Bytecode representation | DEFINITIONS |
---|---|---|
byte | B | byte |
boolean | WITH | bool |
char | C | character |
short | S | Short integer |
int | I | Integer |
float | F | Float |
long | J | Long integer |
double | D | Float |
void | V | Null return value |
class | Ljava / lang / Object; | Object Types |
Array | [] | [ |
Wherein category begins with L, middle class path, and finally ends with; the above array is a single array, be used in conjunction with other types, such as int [] bytecode is [the I, int [] [] Word section code is [[I.
Analytical method
Access modifier has been described above, and JAVA byte code type controls, the following explanation about the analysis method, for example take the above method, as follows:
public java.lang.String getName();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field name:Ljava/lang/String;
4: areturn
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sec/resourceparse/Person;
复制代码
- descriptor: The method described is a method described parameters and return type, the format: (parameter type) return type, there is no representation of the reference value and back String
- flags: a method of access modifiers, shown here as Public
- Code: specific methods described in the stack
- stack: stack allocation maximum depth
- The number of local variables within the method: locals
- args_size: Method Number of parameters
- LineNumberTable: Methods of rows of information (not concerned, did not look)
- LocalVariableTable: the local variable table
Here briefly explain, class methods At least one parameter, the parameter is the class object itself, the equivalent of this keyword, and the subscript is zero.
Bytecode instruction
As already covered the basics bytecode related, but did not elaborate bytecode instructions related content, this section will focus on the content of bytecode instructions, bytecode instructions are divided into the following categories:
- Storing the load type instruction
is loaded into the stack operation parameters or the data stored in the operand stack into local variables, a series of instructions including load, etc. Store instructions and push - Object operation instruction
target instruction including generating a new object from the object property acquiring operations, such as well getStatic putField getField and the like and putStatic - Dup and pop stack management instructions such as push and pop instructions to launch
- Operation instruction
operation instruction data is mainly addition, subtraction instructions, etc., are performed only in operations where the stack - Jump instruction control
ifelse condition determination instructions and the like, and the like goto - Method call and return instructions
including invoke series of instructions and return instruction series, which invoke a method of instruction execution, return is the return series of instructions
Operation Stack Process
Described above has been completed substantially all of the contents of the byte code, where practical method to explain the operation flow. To remember the following points:
JAVA stack-based method of execution is carried out, the method call instruction after the call stack will be out, if the method returns a value, the value will be returned push
First a simple analysis:
public java.lang.String getName();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field name:Ljava/lang/String;
4: areturn
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sec/resourceparse/Person;
复制代码
1.aload_0: where 0 is the first parameter, push type parameter is the object (front analyzed is this)
2.getfield: attribute name acquired from the current top of the stack object and pressing it onto the stack 3.areturn: the current top of the stack is a value of type String, so the return to the use of use areturnRe-introduce a little bit more complicated Liezi:
public class Manager {
public static void main(String [] args) {
String resPath = "/Users/Desktop/resources.arsc";
FileInputStream ins = null;
ByteArrayOutputStream ous = null;
try {
ins = new FileInputStream(new File(resPath));
ous = new ByteArrayOutputStream();
int length = -1;
byte data[] = new byte[4 * 1024];
while ((length = ins.read(data)) != -1) {
ous.write(data, 0, length);
}
byte[] resData = ous.toByteArray();
ParseUtils.parseRes(resData);
} catch (Exception e) {
e.printStackTrace();
}
}
}
复制代码
Corresponding to the byte code as follows:
public com.sec.resourceparse.Manager();
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 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sec/resourceparse/Manager;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=5, locals=7, args_size=1
0: ldc #2 // String /Users/Desktop/resources.arsc
2: astore_1
3: aconst_null
4: astore_2
5: aconst_null
6: astore_3
7: new #3 // class java/io/FileInputStream
10: dup
11: new #4 // class java/io/File
14: dup
15: aload_1
16: invokespecial #5 // Method java/io/File."<init>":(Ljava/lang/String;)V
19: invokespecial #6 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
22: astore_2
23: new #7 // class java/io/ByteArrayOutputStream
26: dup
27: invokespecial #8 // Method java/io/ByteArrayOutputStream."<init>":()V
30: astore_3
31: iconst_m1
32: istore 4
34: sipush 4096
37: newarray byte
39: astore 5
41: aload_2
42: aload 5
44: invokevirtual #9 // Method java/io/FileInputStream.read:([B)I
47: dup
48: istore 4
50: iconst_m1
51: if_icmpeq 66
54: aload_3
55: aload 5
57: iconst_0
58: iload 4
60: invokevirtual #10 // Method java/io/ByteArrayOutputStream.write:([BII)V
63: goto 41
66: aload_3
67: invokevirtual #11 // Method java/io/ByteArrayOutputStream.toByteArray:()[B
70: astore 6
72: aload 6
74: invokestatic #12 // Method com/sec/resourceparse/ParseUtils.parseRes:([B)V
77: goto 87
80: astore 4
82: aload 4
84: invokevirtual #14 // Method java/lang/Exception.printStackTrace:()V
87: return
复制代码
The Manager only declares a static main method, but there are ways a bytecode init, in fact, the default constructor with no arguments, look at the byte code of this method:
public com.sec.resourceparse.Manager();
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 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sec/resourceparse/Manager;
复制代码
1.aload_0: this object will be pushed onto the stack
2.invokespecial: invoke special methods init stack object method, the type of the return value init V, so after the call stack is empty
3.return: Since there is no stack value, so the return instruction executed directly on it
Re-focus look another way:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=5, locals=7, args_size=1
0: ldc #2 // String /Users/Desktop/resources.arsc
2: astore_1
3: aconst_null
4: astore_2
5: aconst_null
6: astore_3
7: new #3 // class java/io/FileInputStream
10: dup
11: new #4 // class java/io/File
14: dup
15: aload_1
16: invokespecial #5 // Method java/io/File."<init>":(Ljava/lang/String;)V
19: invokespecial #6 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
22: astore_2
23: new #7 // class java/io/ByteArrayOutputStream
26: dup
27: invokespecial #8 // Method java/io/ByteArrayOutputStream."<init>":()V
30: astore_3
31: iconst_m1
32: istore 4
34: sipush 4096
37: newarray byte
39: astore 5
41: aload_2
42: aload 5
44: invokevirtual #9 // Method java/io/FileInputStream.read:([B)I
47: dup
48: istore 4
50: iconst_m1
51: if_icmpeq 66
54: aload_3
55: aload 5
57: iconst_0
58: iload 4
60: invokevirtual #10 // Method java/io/ByteArrayOutputStream.write:([BII)V
63: goto 41
66: aload_3
67: invokevirtual #11 // Method java/io/ByteArrayOutputStream.toByteArray:()[B
70: astore 6
72: aload 6
74: invokestatic #12 // Method com/sec/resourceparse/ParseUtils.parseRes:([B)V
77: goto 87
80: astore 4
82: aload 4
84: invokevirtual #14 // Method java/lang/Exception.printStackTrace:()V
87: return
复制代码
Method explanation:
- ([Ljava / lang / String;) V: String parameter is a one-dimensional array, no return value
- flags: access modifier for the static and the public
Stack operation Explanation:
0: Object push type String, value: "/ Users / Desktop / resources.arsc "
- Pop the top element 1 and the presence of local variables
- The null onto the stack
- Pop the top element null, and the presence of local variable 2
- The null onto the stack
- Pop the top element null, and there is a local variable. 3
After completion of the above operation, the stack and local variables methods are as follows:
7-30:
- a new java / io / FileInputStream objects, and pushed onto the stack
- dup: The above object is generated and then pushed onto the stack, there are two current stack of objects FileInputStream
- a new java / io / File objects, and pushed onto the stack
- dup: File object would then pushed onto the stack generated in the above, there are two current stack a File object
- aload_1: 1 local variables onto the stack, i.e. the value onto the stack String
- invokespecial: File calling the init method, parameter is String, no return value Description: 5-6 is to create out of the File object, calling its constructor process, there should figure out why after you create the object to be pressed twice the stack
- invokespecial: FileInputStream object's method call, the parameters are File, no return value
- astore_2: The top element 2 is stored into local variables
- a new java / io / ByteArrayOutputStream objects, and pushed onto the stack
- dup: The above object is generated and then pushed onto the stack, there are two current stack objects ByteArrayOutputStream
- invokespecial: call the init method of ByteArrayOutputStream
- The top element stored into local variable 3
31-42
- iconst_m1: -1 is pushed onto the stack
- istore 4: pop the stack, local variables stored into 4
- sipush 4096: 4096 int type the number onto stack
- newarray: out of stack, create an array, and pushed onto the stack
- astore 5: pop-up element into the stack and local variable 5
- aload_2: local variables onto the stack 2
- aload 5: The local variables onto the stack 5
- invokevirtual: performing FileInputStream read method, the parameter byte array, int return value
- dup: Copy the top element, and pushed onto the stack
- istore 4: pop the top element and stored in local variables 4
- iconst_m1: -1 is pushed onto the stack and then
- if_icmpeq 66: Comparison of the stack 2 int number are equal, equal, direct jump to the line 66, is responsible for implementing the following logic
The basic logic of the above analysis thus, this method is relatively long, do not continue down analysis, is the same step
The key process stack operation: All operations are accompanied by the stack push and logic, such as a method call, using the class parameter and the stack is popped, if the method returns a value, the return value of pressure stack.
to sum up
Bytecode knowledge is quite important to understand the bytecode JVM knowledge can clearly understand the operational mechanism, as well as the back of directly operated bytecode AOP basis.
Reference:
segmentfault.com/a/119000000... my.oschina.net/ta8210/blog...