飞天,一文让你理解Java字节码,前列腺钙化灶

或许你写了许多行的代码,或许你能十分溜的运用高档言语,可是你未必了解那些高档言语的履行进程。例如无人知晓的夏天清晨大行其道的Java。

Java号称是一门“一次编译处处运转”的言语,可是咱们对这句话的了解深度又有多少呢?从咱们写的java文件到经过编译器编译成java字节码文件(也便是.class文件),这个进程是java编译进程;而咱们的java虚拟机履行的便是字节码文件。不管该字节码文件来自何方,由哪种编译器编译,乃至是手写字节码文件,只需契合java虚拟机的标准,那么它就能够履行该字节码文件。那么本文首要讲讲java字节码文件相关常识。接下来咱们经过详细的Demo来深化了解:

1 首要咱们来写一个java源文件

javasrc.png

上面是咱们写的一个java程序,很简单,只要一个成员变量a以及一个办法testMethod() 。

2 接下来咱们用javac指令或许ide东西将该java源文件编译成java字节码文件。

demo.png

上图是编译好的字节码文件,咱们能够看到一堆16进制的字节。假如你运用IDE去翻开,或许看到的是现已被反编译的咱们所了解的java代码,而这才是纯粹的字节码,这也是咱们今日需求讲的内容要点。

或许你会对这样一堆字节码感到头疼,不过不要紧,咱们渐渐试着你看懂它,或许有不一样的收成。在开端之前咱们先来看一张图

java_byte.jpeg

这张图是一张java字节码的总览图,咱们也便是依照上面的次序来对字节码进行解读的。总共含有10部分,包含魔数,版别号,常量池等等,接下来咱们依照次序一步一步解读。

3.1飞天,一文让你了解Java字节码,前列腺钙化灶 魔数

从上面的总览图中咱们知道前4个字节标明的是魔数,对应咱们Demo的是 0XCAFE BABE。什么是魔数?魔数是用来区别文件类型的一种标志,一般都是用文件的前几个字节来标明。比方0XCAFE BABE标明的是class文件,那么有人会问,文件类型能够经过文件名后缀来判别啊?是的,可是文件名是能够修正的(包含后缀),那么为了确保文件的安全性,将文件类型写在文件内部来确保不被篡改。

从java的字节码文件类型咱们看到,CAFE BABE翻译过来是咖啡宝物之意,然后再看看java图标。

java_ico寻尸秘录n.png

CAFE BABE = 咖啡。

3.2 版别号

咱们识别了文件类型之后,接下来要知道版别号。版别号含主版别号和次版别号,都是各占2个字节。在此Demo种为0X0000 0033。其间前面的0000是次版别号,后边的0033是主版别号。经过进制转化得到的是次版别号为0,主版别号为51。

从oracle官方网站咱们能够知道,51对应的正式jdk1.7,而其次版别为0,所以该文件的版别为1.7.0。假如需求验证,能够在用java –version指令输出版别号,或许修正编译方针版别–target从头编译,检查编译后的字节码文件版别号是否做了相应的修正。

至此,咱们共了解了前8字节的意义,下面讲讲常量池相关内容。

3.3 常量池

紧接着主版别号之后的便是常量池进口。常量池是Class文件中的资源库房,在接下来的内容中咱们会发现许多当地会触及,如Class Name,Interfaces等。常量池中首要存储月宫疑云2大类常量:字面量和符号引证。字面量如文本字符串,java中声明为final的常量值等等,而符号引证如类和接口的大局限制名,字段的称号和描绘符,办法的称号和描绘符。

为什么需求类和接口的大局限制名呢?体系引证类或许接口的时分不是经过内存地址进行操作吗?这儿咱们细心想想,java虚拟机在没有将类加载到内存的时分底子都没有分配内存地址,也就不存在对内存的飞天,一文让你了解Java字节码,前列腺钙化灶操作,所以java虚拟机首要需求将飞天,一文让你了解Java字节码,前列腺钙化灶类加载到虚拟机中,那么这个进程规划对类的定女孩白袜位(需求加载A包下的B类,不能加载到其他包下面的其他类中),所以需求通飞天,一文让你了解Java字节码,前列腺钙化灶过大局限制名来判别唯一性。这便是为什么叫做大局,限制的意思,也便是唯一性。

在进行详细常量池剖析之前,咱们先来了解一下常量池的项目类型表:

jvm_constant.png

上面的表中描绘了11中数据类型的结构,其实在jdk1.7之后又增加了3种(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)。这样算起来总共是14种。接下来咱们依照Demo的字节码进行逐个翻译。

00015:由于常量池的数量不固定(n+2),所以需求在常量池的进口处放置一项u2类型的数据代表常量池数量。因而该16进制是21,标明有20项常量,索引规模为1~20。分明是21,为何是20呢?由于Class文件格局规则,规划者就讲第0项保存出来了,以备后患。从这儿咱们知道接下来咱们需求翻译出20项常量。

Constant #1 (总共有20个常量,这是第一个,以此类推…)

0x0a-:从常量类型表中咱们发现,第一个数据均是u1类型的tag,16进制的0a是十进制的10,对应表中的Metho飞天,一文让你了解Java字节码,前列腺钙化灶dRef_info。

0x-00 04-:Class_info索引项#4

0x-00 11-:NameAndType索引项#17

Constant #2

0x-09: FieldRef_info

00003 :Class_info索引项#3

00012:NameAndType索引项#18

Constant #3

007-: Class_info

0x-00 13-: 大局限制名常量索引为#19

Constant #4

0x-07 :Class_info

00014:大局限制名常量索引为#20

Constant #5

001:Utf-8_info

0x-00 01-:字符串长度为1(挑选接下来的一个字节长度转义)

0x-61:”a”(十六进制转ASCII字符)

Constant #6

001:Utf-8_愿望国度info

0x-00 01:字符串长度为1

0x-49:”I”

Constant #7

001:Utf-8_info

0x-00 06:字符串长度为6

0x-3c 696e 6974 3e-:”

Constant #8

001 :UTF-8_info

00003:字符串长度为3

02829 56:”()V”

Constant #9

0x-01:Utf-8_info

00004:字符串长度为4

0x436f 6465:”Code”

Constant #10

001:Utf-8_info

000 0f:字符串长度为1萝莉动态5

0x4c 696e 654e 756d 6265 7254 6162 6c65:”LineNumberTable”

Constant #11

ox01: Utf-8_info

000青云记黄海川免费阅览 12字符串长度为18

0x-4c 6f6镇原刘海龙3 616c 5661 7269 6162 6c65 5461 626c 65:”LocalVariableTable”

Constant #12

001:Utf-8_info

00004 字符串长度为4

07468 6973 :”this”

Constant #13

001:Utf-8_info

0x0f:字符串长度为15

0x4c 636f 6d2f 6465 6d6f 2f44 656d 6f3b:”Lcom/demo/Demo;”

Constant #14

001:Utf-8_info

000 0a:字符串长度为10

ox74 6573 744d 6574 686f 64:”testMethod”

Constant #15

001:Utf-8_info

0x000a:字符串长度为10

0x536f 7572 6365 4669 6c65 :”SourceFile”

Constant #16

001:Utf-8_info

00009:字符串长度为9

0x-44 656d 6f2e 6a61 7661 :”Demo.java”

Constant #17

0x0c :NameAndType_info

00007:字段或许姓称号号常量项索引#7

00008:字段或许办法描绘符常量索引#8

Con袁东操新浪博客stant #18

0x0c:NameAndType_info

00005:字段或许姓称号号常鬼面车神量项索引#5

00006:字段或许办法描绘符常量索引#6

Constant #19

001:Utf-8_info

000 0d:字符串长度为13

063 6f6d 2f64 656d 6f2f 4465 6d6f:”com/demo/Demo”

Constant #20

001:Utf-8_info

000 10 :字符串长度为16

0x6a 6176 612f 6c61 6e67 2f4f 626a 6563 74 :”java/lang/Object”

到这儿停止咱们解析了一切的常量。接下来是解析拜访标志位。

3.4 Access_Flag 拜访标志

拜访标志信息包含该Class文件是类仍是接口,是否被界说成public,是否是abstract,假如是类,是否被声明成final。经过上面的源代码,咱们知道该文件是类并且是public。

access_flag.png

0x 00 21:是00020和00001的并集。其间00020这个标志值触及到了字节码指令,后期会有专题对字节码指令进行解说。等待中……

3.5 类索引

类索引证于确认类的全限制名

000 03 标明引证第3个常量,一起第3个常量引证第19个常量,查找得”com/demo/Demo”。#3.#19

3.6父类索引

000 04 同理:#4.#20(java/lang/Object)

3.7 接口索引

经过java_byte.jpeg图咱们知道,这个接口有2+n个字节,前两个字节标明的强制绝顶是接口数量,后边跟着便是暗恋公式风染白完整版接口的表。咱们这个类没有任何接口,所以应该是0000。果不其然,查找字节码文件得到的便是0000。

3.8 字段表调集

字段表用于描绘类和接口中声明的变量。这儿的字段包含了类等级变量以及实例变量,可是不包含办法内部声明的局部变量。

相同,接下来便是2+n个字段特点。咱们只要一个特点a,按道理应该是0001。查找文件果不其然是0001。

那么接下来咱们要针对这样的字段进行解析。附上字段表结构图

字段表结构.png

000 02 :拜访标志为private(自行查找字段拜访标志)

000 05 : 字段称号索引为#5,对应的是”a”

0x 00 06 :描绘符索引为#6,对应的是”I”

0x 00 00 :特点表数量为0,因车虫小宋电视剧全集此没有特点表。

tips:一些不太重要的表(字段,办法拜访标志表)能够自行查找,这儿就不贴出来了,避免篇幅过大。

3.9 办法

咱们只要一个办法testMethod,依照道理应该前2个字节是0001。经过查找发现是000 02。这是什么原人蛇之恋因,这代表着有2绚烂人生第二部佳恩个办法呢?且持续看……

办法表结构.png

上图是一张办法表结构图,依照这个图咱们剖析下面的字节码:

第1个办法:与黑人

000 cb锁01:拜访标志 ACC_PUBLIC,标明该办法是public。(可自行查找办法拜访标志表)

000 07:办法名索引为#7,对应的是”

000 08:办法描绘符索引为#8,对应的是”()V”

000 01:特点表数量为1(一个特点表)

那么这儿触及到了特点表。什么是特点表呢?能够这么了解,它是为了描绘一些专有信息的,上面的办法带有一张特点表。一切特点表的结构如下图:

一个u2的特点称号索引,一个u2的特点长度加上特点长度的info。

虚拟机标准预界说的特点有许多,比方Code,LineNumberTable,LocalVariableTable,SourceFile等等,这个网上能够查找到。

特点表结构.png

依照上面的表结构解析得到下面信息:

00009:称号索引为#9(“Code”)。

0000 00038:特点长度为56字节。

那么接下来解析一个Code特点表,依照下图解析

code.png

前面6个字节(称号索引2字节+特点长度4字节)现已解析过了,所以接下来便是解析剩余的56-6=50字节即可。

000 02 :max_stack=2

000 01 : max_locals=1

000 0000 0a : code_length=10

0x2a b700 012a 04b5 0002 b1 : 这是code代码,能够经过虚拟机字节码指令进行查找。

2a=aload_0(将第一个引证变量推送到栈顶)

b7=invokespecial(调用父类结构办法)

00=什么都不做

01 =将null推飞天,一文让你了解Java字节码,前列腺钙化灶送到栈顶

2a=同上

04=iconst_1 将int型1推送到栈顶

b5=putfield 为指定的类的实例变量赋值

00= 同上

02=iconst_m1 将int型-1推送栈顶

b1=return 从当时办法维尼是谁回来void

收拾,去除无动作指令得到下面

0 : aload_0

1 : invokespecial

4 : aload_0

5 : iconst_1

6 : putfield

9 : return

关于虚拟机字节码指令这块内容,后期会持续深化下去…… 现在只需求了解即可。接下来顺着Code特点表持续解析下去:

000 00 : exception_table_length=0

000 02 : attributes_count=2(Code特点表内部还含有2个特点表)

000 0a: 第一个特点表是”LineNumberTable”

LineNumberTable.png

000 0000 0a : “特点长度为10″

000 02 :line_number_table_length=2

line_number_table是一个数量为line_number_table_length,类型为line_number_info的调集,line_number_info表包含了start_pc和line_number两个u2类型的数据项,前者是字节码行号,后者是Java源码行号

000 00 : start_pc =0

000 03 : end_pc =3

000 04 : start_pc=4

000 04 : end_pc=4

000 0b 第二个特点表是:”LocalVariableTable”



local_variable_table.png

local_variable_info.png

000 0000 0c:特点长度为12

000 01 : local_variable_table_length=1

然后依照local_variable_info表结构进行解析:

000 00 : start_pc=0

000 0a:length=10

0x000c : name_index=”this”

0x000d : descriptor_index #13 (“Lcom/demo/Demo”)

0000 index=0

//——-到这儿第一个办法就解析完成了——-//

M石涛评述ethod()–1个特点Code表-2个特点表(LineNumberTable ,LocalVariableTable)接下来解析第二个办法

第2个办法:

000 04:”protected”

000 0e: #14(”testMethod”)

000 08 : “()V”

00001 : 特点数量=1

00009 :”Code”

00000 002b 特点长度为43

解析一个Code表

0000 :max_stack =0

0001 : max_local =1

0000 0001 : code_length =1

0xb1 : return(该办法回来void)

00000 反常表长度=0

00002 特点表长度为2

//第一个特点表

0x000a : #10,LineNumberTable

00000 0006 : 特点长度为6

00001 : line_number_length = 1

00000 : start_pc =0

00008 : end_pc =8

//第二个特点表

0x000b : #11 ,LocalVariableTable

00000 000c : 特点长度为12

00001 : local_variable_table_length =1

00000 :start_pc = 0

00001: l飞天,一文让你了解Java字节码,前列腺钙化灶ength = 1

0x000c : name_index =#12 “this”

0x000d : 描绘索引#13 “Lcom/demo/Demo;”

0000 index=0

//到这儿停止,办法解析都完成了,回过头看看顶部解析次序图,咱们接下来就要解析Attributes了。

3.10 Attribute

00001 :相同的,标明有1个Attributes了。

0x000f : #15(“SourceFile”)

00000 0002 attribute_length=2

00010 : sourcefile_index = #16(“Demo.java”)

SourceFile特点用来记载生成该Class文件的源码文件称号。

source_file.jpeg

4 另话

其实,咱们写了这么多的确很费事,不过这种进程自己体会一遍的所获所得仍是不同的。现在,运用java自带的反编译器来解析字节码文件。

javap -verbose Demo //不必带后缀.class

javap_result.png

5 总结

到此停止,解说完成了class文件的解析,这样今后咱们也能看懂字节码文件了。了解class文件的结构对后边进一步了解虚拟机履行引擎十分重要,所以这是根底并重要的一步。

点击展开全文

上一篇:

下一篇:

相关推荐