字节码文件解析

1、在C盘根目录定义一个带包java类(jdk8)

1
2
3
4
5
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello world");
}
}

2、编译文件

1
javac HelloWorld.java

得到字节码文件

3、使用sublime打开class文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cafe babe 0000 0034 001c 0a00 0600 0f09
0010 0011 0800 120a 0013 0014 0700 1207
0015 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 046d 6169
6e01 0016 285b 4c6a 6176 612f 6c61 6e67
2f53 7472 696e 673b 2956 0100 0a53 6f75
7263 6546 696c 6501 000f 4865 6c6c 6f57
6f72 6c64 2e6a 6176 610c 0007 0008 0700
160c 0017 0018 0100 0a48 656c 6c6f 576f
726c 6407 0019 0c00 1a00 1b01 0010 6a61
7661 2f6c 616e 672f 4f62 6a65 6374 0100
106a 6176 612f 6c61 6e67 2f53 7973 7465
6d01 0003 6f75 7401 0015 4c6a 6176 612f
696f 2f50 7269 6e74 5374 7265 616d 3b01
0013 6a61 7661 2f69 6f2f 5072 696e 7453
7472 6561 6d01 0007 7072 696e 746c 6e01
0015 284c 6a61 7661 2f6c 616e 672f 5374
7269 6e67 3b29 5600 2100 0500 0600 0000
0000 0200 0100 0700 0800 0100 0900 0000
1d00 0100 0100 0000 052a b700 01b1 0000
0001 000a 0000 0006 0001 0000 0002 0009
000b 000c 0001 0009 0000 0025 0002 0001
0000 0009 b200 0212 03b6 0004 b100 0000
0100 0a00 0000 0a00 0200 0000 0400 0800
0500 0100 0d00 0000 0200 0e

4、解析

设想假如某个程序因为不同的硬件平台原因需要编写多套代码,这会令人十分崩溃。

Java的使命就是一次编写、到处执行!!!在不同的操作系统和不同的硬件平台上,可以不用修改

代码即可顺畅地执行,如何实现跨平台?

有一个声音在天空中回响:计算机工程领域的任何问题都可以通过增加一个中间层来解决。

因此,中间码应运而生 - class文件,Java所有的指令有200个左右,一个字节(8位)可以存储256种不

同的指令信息,一个这样的字节称为字节码(Bytecode)。所以Java的class文件又叫做字节码文件

在代码的执行过程中,JVM将字节码进行解释执行,屏蔽对底层操作系统的依赖;JVM也可以将字节

码编译执行,如果是热点代码,会通过JIT动态地编译为机器码,提高执行效率。

字节码文件为十六进制的数列表示,十六进制表示的二进制流通常是一个操作指令。起始的4个字节

非常特殊 – cafe babe(十六进制)是Gosling定义的一个魔法数,意思是Coffee Baby,其十进制值为

3405691582。它的作用是:标志该文件是一个Java类文件,如果没有识别到该标志,说明该文件不

是Java类文件或者文件已受损,无法进行加载。随后的四个字节代表当前版本号(0000 0034),

其中0000是副版本号,0034是主版本号 转为十进制为52.0对应jdk8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
cafe babe 0000 0034
//cafe babe:魔数,java字节码文件的标记
//0000 0034:版本号,其中0000是副版本号,0034是主版本号 转为十进制为52.0对应jdk8
001c
//001c:常量数量 这个值从1开始到constant_pool_count-1结束,共27个常量
0a 0006 000f
//0a 0006 000f:第一个常量 指向一个方法定义 方法定义后面会跟两个字节来存储这个方法指向的类常量,另外两个字节执行方法名字和类型常量,0006指向#6号常量Object类 000f指向初始化方法
09 0010 0011
//09 0010 0011:第二个常量out属性
08 0012
//08 0012:String HelloWorld
0a 0013 0014
//0a 0013 0014:println()方法
07 0012
//07 0012:HelloWorld这个类
07 0015
//07 0015:Object类
01 00 06 3c 696e 6974 3e
//01 0006 3c 69 6e 69 74 3e:字符串"<init>"
01 0003 2829 56
//01 0003 28 29 56:字符串"()V"
01 0004 436f 6465
//01 0004 436f 6465:
0100 0f4c 696e 654e 756d 6265 7254 6162 6c65
//0100 0f4c 696e 654e 756d 6265 7254 6162 6c65
0100 046d 6169 6e
//0100 046d 6169 6e:字符串常量
01 0016 285b 4c6a 6176 612f 6c61 6e67 2f53 7472 696e 673b 2956
//01 0016 285b 4c6a 6176 612f 6c61 6e67 2f53 7472 696e 673b 2956:字符串常量
0100 0a53 6f75 7263 6546 696c 65
//01 000a 53 6f75 7263 6546 696c 65:字符串常量
01 000f 4865 6c6c 6f57 6f72 6c64 2e6a 6176 61
//01 000f 4865 6c6c 6f57 6f72 6c64 2e6a 6176 61:字符串常量
0c 0007 0008
//0c 0007 0008:NameAndType类型 <init>()V
0700 16
//07 0016:System类
0c 0017 0018
//0c 0017 0018:NameAndType类型 PrintStream()
0100 0a48 656c 6c6f 576f 726c 64
//01 000a 48 656c 6c6f 576f 726c 64:字符串常量
07 0019
//07 0019:PrintStream类
0c00 1a00 1b
//0c 001a 001b:println()
01 0010 6a61 7661 2f6c 616e 672f 4f62 6a65 6374
//01 0010 6a61 7661 2f6c 616e 672f 4f62 6a65 6374:字符串常量
01 00106a 6176 612f 6c61 6e67 2f53 7973 7465 6d
//01 0010 6a 6176 612f 6c61 6e67 2f53 7973 7465 6d:字符串常量
01 0003 6f75 74
//01 0003 6f75 74:字符串常量
01 0015 4c6a 6176 612f 696f 2f50 7269 6e74 5374 7265 616d 3b
//01 0015 4c6a 6176 612f 696f 2f50 7269 6e74 5374 7265 616d 3b:字符串常量
01 0013 6a61 7661 2f69 6f2f 5072 696e 7453 7472 6561 6d
//01 0013 6a61 7661 2f69 6f2f 5072 696e 7453 7472 6561 6d:字符串常量
01 0007 7072 696e 746c 6e
01 0015 284c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b29 56
//上面两行也是存储的字符串常量
0021
//0021:access_flags = 0020+0001:public + super
0005
//0005:this_class:当前类HelloWorld
0006
//0006:super_class:Object
0000
//0000:接口数量为0
0000
//0000:字段数量为0
0002
//0002:方法个数,默认加了初始化方法
0001 00 0700 08 00 0100 0900 0000 1d
00 0100 0100 0000 052a b700 01b1 0000 0001 000a 0000 0006 0001 0000 0002
//0001:public 方法的访问修饰符
//0007:init
//0008:()V
//0001:属性个数--1个
//0009:Code 虚拟机对方法说明
//00 0000 1d:Code内容长度29 后面的就是Code存储的内容
0009 000b 000c 0001 0009 0000 0025 0002 0001
0000 0009 b200 0212 03b6 0004 b100 0000
0100 0a00 0000 0a00 0200 0000 0400 0800 05
//0009:public+static
//000b:main()
//000c:String[] args
//0001:属性个数--1个
//0009:Code 虚拟机对方法说明
//0000 0025:37个字节长度
//至此,方法结束
0001 00 0d00 0000 0200 0e
//0001:attributes_count:1
//000d:sourceFile
//0000 0002:信息长度
//000e:指向常量HelloWorld.java