java 原文件通过编译器编译为.class 二进制文件,在通过 jvm 解释器将二进制文件转换成可执行文件,进行执行

创建一个 test.java 得源文件:
public class test {
public static void main(String[] args) {
int a = 10;
a = 100;
int b = 10;
int c = a + b;
System.out.print(c);
}
}
打开 cmd,通过 javac test.java 编译为.class 文件,javap -v test.class > test.txt 命令可以得到 text.class 二进制的指令码
Classfile /D:/project/xuexi/test.class
Last modified 2022-8-13; size 405 bytes
MD5 checksum 3f86f6f81a0a9a0c4ed96e26c2f29d3a
Compiled from "test.java"
public class test
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #5.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #17.#18 // java/io/PrintStream.print:(I)V
#4 = Class #19 // test
#5 = Class #20 // java/lang/Object
#6 = Utf8 <init>
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 main
#11 = Utf8 ([Ljava/lang/String;)V
#12 = Utf8 SourceFile
#13 = Utf8 test.java
#14 = NameAndType #6:#7 // "<init>":()V
#15 = Class #21 // java/lang/System
#16 = NameAndType #22:#23 // out:Ljava/io/PrintStream;
#17 = Class #24 // java/io/PrintStream
#18 = NameAndType #25:#26 // print:(I)V
#19 = Utf8 test
#20 = Utf8 java/lang/Object
#21 = Utf8 java/lang/System
#22 = Utf8 out
#23 = Utf8 Ljava/io/PrintStream;
#24 = Utf8 java/io/PrintStream
#25 = Utf8 print
#26 = Utf8 (I)V
{
public test();
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
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: bipush 10
2: istore_1
3: bipush 100
5: istore_1
6: bipush 10
8: istore_2
9: iload_1
10: iload_2
11: iadd
12: istore_3
13: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_3
17: invokevirtual #3 // Method java/io/PrintStream.print:(I)V
20: return
LineNumberTable:
line 6: 0
line 7: 3
line 8: 6
line 9: 9
line 10: 13
line 11: 20
}
SourceFile: "test.java"
我们可以参照指令码表 (https://www.cnblogs.com/cycheng/p/14469871.html),查看每条指令是什么意思
执行时,
3: bipush 100 将 100 压入操作数栈,程序计数器变为 3
5: istore_1 将 100 放入到本地变量表 1,清空操作数栈,程序计数器变为 5
6: bipush 10 同上执行
8: istore_2 同上执行
9: iload_1
10: iload_2
11: iadd
12: istore_3
将本地变量表位置 1,2 加载到操作数栈,进行相加操作,然后放入本地变量表位置 3
小结:
主要是说明,jvm 如何执行字节码文件,而 jvm 针对不同的操作系统又有不同的实现,所以也是 java 能够实现一处编写,处处运行的原因
版权声明:本文为u010562991原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。