Java bytecode is an instruction format that the JVM executes, using bytecode instructions to perform corresponding actions
Bytecode viewing (mnemonic -> binary)
The.class file itself is a binary file, and we can view it in two ways. One is to view its binary contents directly, which is not easy to view and understand, and the other is to see its contents in mnemonic mode through Javap, which is easy to understand
Binary viewing mode
Binary viewer
Since binary files in computers are usually escaped by text editors when opened, it is recommended to use software such as Winhex for easy understanding
Mnemonic view
javap
You can use the javac command to compile.java files into.class files, which are called Java bytecode files.
You can run the javap -c command to view the bytecode of the. Class file.
You can run the javap -c -verbose command to view detailed information about bytecode.
The IDEA of the plugin
The Jclasslib Bytecode Viewer plug-in makes it easy to view the compiled Bytecode files of each Java class
Simple bytecode parsing
Java code before compilation
package com.rrtx.adm;
/** * Created by yarne on 2021/7/3. */
public class Main {
public static void main(String[] args) {
int a = 5;
double b = 2.00;
String c = "3";
add(c,a,b);
}
public static void add(String a,int b,double c){
doublev = Integer.valueOf(a) + b + c; System.out.println(v); }}Copy the code
View bytecode (mnemonic) for.class
Classfile /C:/Users/14641/Desktop/Main.class
Last modified 2021-7-4; size 890 bytes
MD5 checksum 683b4cdcd60108ce5bfdcc9e6fe3c992
Compiled from "Main.java"
public class com.rrtx.adm.Main
minor version: 0
major version: 52
flags: ACC_PUBLIC.ACC_SUPER
Constant pool# 1:= Methodref #11.#34 // java/lang/Object."<init>":()V
#2 = Double 2.0 d
#4 = String #35 / / 3
#5 = Methodref #10.#36 // com/rrtx/adm/Main.add:(Ljava/lang/String; ID)V
#6 = Methodref #37.#38 // java/lang/Integer.valueOf:(Ljava/lang/String;) Ljava/lang/Integer;
#7 = Methodref #37.#39 // java/lang/Integer.intValue:()I
#8 = Fieldref #40.#41 // java/lang/System.out:Ljava/io/PrintStream;
#9 = Methodref #42.#43 // java/io/PrintStream.println:(D)V
#10 = Class #44 // com/rrtx/adm/Main
#11 = Class #45 // java/lang/Object
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 LocalVariableTable
#17 = Utf8 this
#18 = Utf8 Lcom/rrtx/adm/Main;
#19 = Utf8 main
#20 = Utf8 ([Ljava/lang/String;)V
#21 = Utf8 args
#22 = Utf8 [Ljava/lang/String;
#23 = Utf8 a
#24 = Utf8 I
#25 = Utf8 b
#26 = Utf8 D
#27 = Utf8 c
#28 = Utf8 Ljava/lang/String;
#29 = Utf8 add
#30= Utf8 (Ljava/lang/String; ID)V #31 = Utf8 v
#32 = Utf8 SourceFile
#33 = Utf8 Main.java
#34 = NameAndType #12: #13 // "<init>":()V
#35 = Utf8 3
#36 = NameAndType #29: #30 // add:(Ljava/lang/String; ID)V
#37 = Class #46 // java/lang/Integer
#38 = NameAndType #47: #48 // valueOf:(Ljava/lang/String;) Ljava/lang/Integer;
#39 = NameAndType #49: #50 // intValue:()I
#40 = Class #51 // java/lang/System
#41 = NameAndType #52: #53 // out:Ljava/io/PrintStream;
#42 = Class #54 // java/io/PrintStream
#43 = NameAndType #55: #56 // println:(D)V
#44 = Utf8 com/rrtx/adm/Main
#45 = Utf8 java/lang/Object
#46 = Utf8 java/lang/Integer
#47 = Utf8 valueOf
#48= Utf8 (Ljava/lang/String;) Ljava/lang/Integer; #49 = Utf8 intValue
#50 = Utf8 ()I
#51 = Utf8 java/lang/System
#52 = Utf8 out
#53 = Utf8 Ljava/io/PrintStream;
#54 = Utf8 java/io/PrintStream
#55 = Utf8 println
#56 = Utf8 (D)V
{
public com.rrtx.adm.Main();
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
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/rrtx/adm/Main;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=5, args_size=1
0: iconst_5
1: istore_1
2: ldc2_w #2 / / double 2.0 d
5: dstore_2
6: ldc #4 // String 3
8: astore 4
10: aload 4
12: iload_1
13: dload_2
14: invokestatic #5 // Method add:(Ljava/lang/String; ID)V
17: return
LineNumberTable:
line 8: 0
line 9: 2
line 10: 6
line 11: 10
line 12: 17
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 args [Ljava/lang/String;
2 16 1 a I
6 12 2 b D
10 8 4 c Ljava/lang/String;
public static void add(java.lang.String, int.double); descriptor: (Ljava/lang/String; ID)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=6, args_size=3
0: aload_0
1: invokestatic #6 // Method java/lang/Integer.valueOf:(Ljava/lang/String;) Ljava/lang/Integer;
4: invokevirtual #7 // Method java/lang/Integer.intValue:()I
7: iload_1
8: iadd
9: i2d
10: dload_2
11: dadd
12: dstore 4
14: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
17: dload 4
19: invokevirtual #9 // Method java/io/PrintStream.println:(D)V
22: return
LineNumberTable:
line 16: 0
line 17: 14
line 18: 22
LocalVariableTable:
Start Length Slot Name Signature
0 23 0 a Ljava/lang/String;
0 23 1 b I
0 23 2 c D
14 9 4 v D
}
Copy the code
Structure that
By simply classifying the above bytecode files, you can divide a class into class summaries, constant pools, and method stack frames
The class the
The summary records some basic information about the class, including the size change time, checksum, JDK version information at compile time, and the scope of the class
Classfile /C:/Users/yarne/Desktop/Main.class // From the desktop main. class file
Last modified 2021-7-4; size 890 bytes // Finally modify the time and class size
MD5 checksum 683b4cdcd60108ce5bfdcc9e6fe3c992 / / the checksum
Compiled from "Main.java"
public class com.rrtx.adm.Main
minor version: 0 / /jdkThe child version numbermajor version: 52 / /jdkMajor version 52 means yesjava8
flags: ACC_PUBLIC.ACC_SUPER //publicClass, the initialization method uses the parent classCopy the code
Flags Indicates the meaning of the identifier
Identifier name | The identifier value | paraphrase |
---|---|---|
ACC_PUBLIC | 0x0001 | Public type |
ACC_FINAL | 0x0010 | The Final type |
ACC_SUPER | 0x0020 | Whether the new semantics of the Invokespecial bytecode instruction are allowed |
ACC_INTERFACE | 0x0200 | Interface modifier |
ACC_ABSTRACT | 0x0400 | The abstract modifier |
ACC_SYNTHETIC | 0x1000 | Indicates that this class is not generated by user code |
ACC_ANNOTATION | 0x2000 | Annotation modifier |
**ACC_ENUM | 0x400 | Enumeration modifier |
Constant pool
A constant pool contains all of the primitive type constants ina class and symbolic references. Primitive constants include string constants, final-modified member variables, instance variables, etc. Symbolic references include class and interface names, field names and descriptions, and method names and descriptions
Primitive type constant
Constants of basic type include literals and referrals. Literals include text strings, final variables, and data values. For constants of basic value int, the pool value holds the reference and literal name, but does not hold the value of the data
#2 = Double 2.0 d // Double stores the actual value
#4 = String #35 / / reference # 35
#35 = Utf8 3 // new String("3")
#23 = Utf8 a //int stores only the name, not the actual value
#24 = Utf8 I
Copy the code
Symbolic reference
Symbolic references contain the names and descriptions of many classes, interfaces, fields, methods, and so on
#5 = Methodref #10.#36 // com/rrtx/adm/Main.add:(Ljava/lang/String; ID)V
#6 = Methodref #37.#38 // java/lang/Integer.valueOf:(Ljava/lang/String;) Ljava/lang/Integer;
#7 = Methodref #37.#39 // java/lang/Integer.intValue:()I
#8 = Fieldref #40.#41 // java/lang/System.out:Ljava/io/PrintStream;
#9 = Methodref #42.#43 // java/io/PrintStream.println:(D)V
#10 = Class #44 // com/rrtx/adm/Main
#11 = Class #45 // java/lang/Object
Copy the code
Methods the stack frame
Method stack frames are the methods in the class. Each method is a frame that is defined when the class is compiled, created from the definition when the thread is running, and destroyed when the call ends.
The JVM creates a stack frame for each method called in the current thread. The JVM creates a stack frame for each method called in the current thread. Each stack frame contains the local variable table, operation stack, dynamic link, return address, and some additional summary information. The stack frame is destroyed after being called
Here are all stack frames in main. class. There are two methods.
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=5, args_size=1
0: iconst_5
1: istore_1
2: ldc2_w #2 / / double 2.0 d
5: dstore_2
6: ldc #4 // String 3
8: astore 4
10: aload 4
12: iload_1
13: dload_2
14: invokestatic #5 // Method add:(Ljava/lang/String; ID)V
17: return
LineNumberTable:
line 8: 0
line 9: 2
line 10: 6
line 11: 10
line 12: 17
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 args [Ljava/lang/String;
2 16 1 a I
6 12 2 b D
10 8 4 c Ljava/lang/String;
public static void add(java.lang.String, int.double); descriptor: (Ljava/lang/String; ID)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=6, args_size=3
0: aload_0
1: invokestatic #6 // Method java/lang/Integer.valueOf:(Ljava/lang/String;) Ljava/lang/Integer;
4: invokevirtual #7 // Method java/lang/Integer.intValue:()I
7: iload_1
8: iadd
9: i2d
10: dload_2
11: dadd
12: dstore 4
14: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
17: dload 4
19: invokevirtual #9 // Method java/io/PrintStream.println:(D)V
22: return
LineNumberTable:
line 16: 0
line 17: 14
line 18: 22
LocalVariableTable:
Start Length Slot Name Signature
0 23 0 a Ljava/lang/String;
0 23 1 b I
0 23 2 c D
14 9 4 v D
}
Copy the code
The stack frame in this paper,
From the stack frame summary information, you can basically know the basic information about a method
/ / the main method
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC Static, public methods
Code:
stack=4, locals=5, args_size=1 // The stack frame depth is 4, the maximum local variables are 5, and the number of inputs is 1
/ / the add method
public static void add(java.lang.String, int.double); descriptor: (Ljava/lang/String; ID)V flags: ACC_PUBLIC, ACC_STATICStatic, public methods
Code:
stack=4, locals=6, args_size=3 // The stack frame depth is 4, the maximum local variables are 6, and the number of inputs is 3
Copy the code
Local variable scale
The local variable table is an array used to store local variables of the current method. The types that can be stored in the table include Boolean, byte, CHAR, short, int, float, and reference types. Since local variables are thread private, there is no problem with thread safety. This is done after the.class bytecode file is compiled
// the main method is a local variable table
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 args [Ljava/lang/String; // Enter args as an array of type String
2 16 1 a I // local variable a of type I int
6 12 2 b D // local variable b of type D double
10 8 4 c Ljava/lang/String; // local variable c of type String
// add method local variable table
LocalVariableTable:
Start Length Slot Name Signature
0 23 0 a Ljava/lang/String; // enter parameter A, which is of type String
0 23 1 b I // enter parameter b of type I
0 23 2 c D // enter parameter c, type D
14 9 4 v D // Calculate the value v of type D
Copy the code
The operand stack
The operand stack is also a stack used for calculation. The method execution starts at the empty stack, proceeds to the stack according to the bytecode instructions, and then exits the stack. The stack size is also calculated after the class is compiled. The following is a brief look at the main method operand stack instruction execution flow
// Operand stack of main method
0: iconst_5
1: istore_1
2: ldc2_w #2 / / double 2.0 d
5: dstore_2
6: ldc #4 // String 3
8: astore 4
10: aload 4
12: iload_1
13: dload_2
14: invokestatic #5 // Method add:(Ljava/lang/String; ID)V
17: return
Copy the code
Classification of instructions
According to the nature of instructions, they can be divided into four types:
- Stack manipulation instructions, including instructions to interact with local variables
- Program flow control instructions
- Object manipulation instructions, including method invocation instructions
- Arithmetic operations and type conversion instructions
Key instructions load&store
During a JVM run, all operations are performed on the virtual machine stack, but because the lifecycle of the stack is consistent with that of the thread, the stack is destroyed after each calculation, leaving no data. Therefore, during each stack operation, there will be a key action, which is to load data from the local variable table first, and then store it back after calculation
Common instruction types (just a few above)
- Load and store instructions load and store
- Constants define const
- LDC complex type definition
- Basic types :iconst, istore, iload I, which means int, and so on
I stands for int, L for long, S for short, B for byte, C for char, F for float, D for double, and a, unlike the others, is a reference typeCopy the code
-
Invokestatic invokes static methods
-
The stack return
Operation process
0: define a constant of type int as 5 1: store the constant of type int off the stack into an array of constants in slot 1 2: define type double 2.0 using the complex type referenced in #2 5: Insert a constant of type double into an array of constants in slot 2. 6: Define a String of type 3 using the complex type referenced in #4. 10: insert slot 4 into the constants array 12: insert slot 1 into the constants array 13: insert slot 2 into the constants array double 15: call the frame reference symbol #5 17: unstackCopy the code
conclusion
The above briefly introduced the way to view bytecode, the structure of bytecode files, and how to understand the bytecode runtime structure. As mentioned above, JVM is based on stack calculation, so understanding the stack and runtime structure can help me to have a deeper understanding of the actions of JVM stack runtime.
Finally, a cumbersome sentence is used to describe the call process between the thread stack and stack frame
Thread creation -> Thread stack Creation -> Call Stack FRAME A-> Call Stack Frame A-> Call stack Frame A-> Call stack Frame B-> Call stack Frame B-> Call stack Frame B-> Return stack Frame B-> Return stack Frame A-> Destroy stack Frame A-> Destroy thread stack -> Destroy thread
Reference:
www.lagou.com/lgeduarticl…
Segmentfault.com/a/119000003…
Infringement to delete