复杂字节码文件的分析过程
上一次【https://www.cnblogs.com/webor2006/p/9595300.html】了解了synchronized关键字在字节码中的表现形式了,接下来则从头至尾完整的对以下这个稍复杂的字节码文件进行分析,其源文件为:
其对于应二进制字节码信息用“Hex Fiend”打开:
可以发现此次的要比上一次的要复杂多了,所以说硬着头皮再来完整的分析一遍,因为源文件该有的信息基本上都已经有了,操练一次之后关于字节码的东东基本上也就学得比较扎实了,当然这一次分析不会像上一次那么详细,毕境熟练之后分析也会用稍快的方式,在正式分析之前首先得回忆一下Java字节码的整体结构,如下:
总共有10个部分,下面一个个部分进行分析:
Magic Number:
数四个字节:
不多说了~
Version:
往后数四个字节:
为52,为JDK1.8,其中minor_version和major_version如下:
Constant Pool:
这部分内容是最多的,先来数2个字节代表有多少个常量:
也就是有71个常量,查看一下jclasslib是否是这样:
其中常量索引0为保留常量,为对应的null值,而对咱们有用的常量索引是从1开始的【关于这个理论可以回顾:https://www.cnblogs.com/webor2006/p/9410518.html】,所以总共看到的就是70个常量,下面则一个个来对它进行完整分析,坚持!!!确实是比较枯燥,在分析之前先来回顾一下常量类型表,如下:
常量一:
其中第一个字节都为常量的类型,所以往后数1个字节:
10对应常量类型表中的它:
接着2个字节则为方法类描述符的索引项,对应这两个字节:
索引是12,接着两个字节则为名称及类型描述符的索引,所以再往后数2个字节:
索引是45,所以看一下javap -verbose所示:
常量二:
往后数一个字节:
查找一下常量类型表:
所以往后数2个字节:
对应索引46,对应javap -verbose:
正好对应源代码中的这个地方:
常量三:
数一个字节查看常量类型:
查找常量表,对应类型为:
往后数两个字节则字段类描述符索引为:
再接着两个字节则为名称及类型描述符的索引,所以再往后数2个字节:
索引为47,所以对就javap -verbose为:
刚好描述的就是字段str:
常量四:
数一个字节查看常量类型:
查找常量表,跟上一个常量类型一样,所以往后数两个字节则字段类描述符索引为:
再接着两个字节则为名称及类型描述符的索引,所以再往后数2个字节:
对应索引48,所以对应javap -verbose为:
描述就是成员变量x的信息:
常量五:
数一个字节查看常量类型:
查找常量表,对应类型为:
所以往后数两个字节则为类的全限定名常量索引:
索引为49,所以对应javap -verbose为:
常量六:
数一个字节查看常量类型:
查找常量表,对应类型为:
描述的是方法信息,数2个字节表示是类描述符索引:
再数2个字节则为方法名称及类型描述符索引:
对应javap -verbose,如下:
描述的是默认的构造方法。
常量七:
数一个字节查看常量类型:
跟上一个常量类型一样,也是方法描述,所以再数四个字节则分别代表方法类和方法名称及类型描述符索引,如下:
对应javap -verbose,如下:
对应于源代码:
常量八:
数一个字节查看常量类型:
又是方法描述,所以往后再数四个字节:
对应于javap -verbose如下:
很明显咱们没有定义valueOf这个方法呀,当然不是我们定义的,而是由于这句话会自动进行装箱,其中底层就是调用的此方法,如下:
常量九:
数一个字节查看常量类型:
查找常量表,对应类型为:
所以往后数四个字节:
对应javap -verbose如下:
描述的是它:
常量十:
数一个字节查看常量类型:
跟上一个常量类型一样,表示字段信息,所以往后数四个字节,如下:
对应于javap -verbose:
虽说咱们没有定义这个成员变量,但是下面的它用到了:
常量十一:
数一个字节查看常量类型:
查找常量表,对应类型为:
表示一个字符串信息,所以往后数2个字节:
对应于javap -verbose:
对应源文件:
常量十二:
数一个字节查看常量类型:
查找常量表,对应类型为:
往后数2个字节:
对应javap -verbose:
常量十三:
数一个字节查看常量类型:
查找常量表,对应类型为:
所以往后数四个字节:
对应于javap -verbose:
很明显描述的是打印方法:
常量十四:
数一个字节查看常量类型:
查找常量表,对应类型为:
往后数2个字节为字符串的长度:
长度为3,再数三个字节则为字符串内容:
对应于javap -verbose:
描述的是这个变量名:
常量十五:
数一个字节查看常量类型:
又是一个字符串,所以往后数2个字节来看一下字符串的长度:
往后数18个字节:
其Hex Fiend右侧就可以看到其字符串的内容了“Ljava/lang/String;”,对应一下javap -verbose:
常量十六:
数一个字节查看常量类型:
又是一个字符串,所以往后数2个字节来看一下字符串的长度:
往后数1个字节:
也就是描述的是这个变量的名字:
常量十七:
数一个字节查看常量类型:
往后数两个字节:
往后数1个字节:
对应于javap -verbose:
常量十八:
数一个字节查看常量类型:
依然跟上一个常量类型一样,往后数两个字节:
往后数两个字节:
对应于javap -verbose:
对就是对应于in变量:
常量十九:
数一个字节查看常量类型:
同样的类型,继续往后数2个字节:
往后数19个字节:
对应于javap -verbose:
常量二十:
数一个字节查看常量类型:
又是同样的类型,往后数2个字节:
往后数6个字节:
对应于javap -verbose:
常量二十一:
数一个字节查看常量类型:
又是同一个字符常量类型,往后数2个字节:
再往后数3个字节:
常量二十二:
数一个字节查看常量类型:
同样的先数2个字节:
再数4个字节:
对应于javap -verbose:
其实一看到Code信息就说明是方法的代码信息了。
常量二十三:
数一个字节查看常量类型:
往后数2个字节:
往后数15个字节:
对应javap -verbose:
常量二十四:
数一个字节查看常量类型:
往后数2个字节:
往后数18个字节:
对应于javap -verbose:
常量二十五:
数一个字节查看常量类型:
往后数2个字节:
再往后数4个字节:
对应于javap -verbose:
常量二十六:
数一个字节查看常量类型:
往后数2个字节:
往后数26个字节:
对应javap -verbose:
常量二十七:
数一个字节查看常量类型:
往后数2个字节:
再往后数4个字节:
对应于javap -verbose:
常量二十八:
数一个字节查看常量类型:
往后数两个字节:
往后数22个字节:
对应于javap -verbose:
常量二十九:
数一个字节查看常量类型:
往后数2个字节:
往后数4个字节:
对应于javap -verbose:
常量三十:
数一个字节查看常量类型:
往后数2个字节:
再往后数19个字节:
对应于javap -verbose:
常量三十一:
数一个字节查看常量类型:
往后数2个字节:
往后数7个字节:
对应于javap -verbose:
常量三十二:
数一个字节查看常量类型:
往后数2个字节:
再往后数四个字节:
对应于javp -verbose:
常量三十三:
数一个字节查看常量类型:
再往后数2个字节:
往后数四个字节:
对应javap -verbose:
实际上也就是setX()方法的方法描述符。
常量三十四:
数一个字节查看常量类型:
再往后数2个字节:
再往后数4个字节:
对应于javap -verbose:
实际上就是下面这个方法的方法名:
常量三十五:
数一个字节查看常量类型:
往后数2个字节:
往后数21个字节:
对应于javap -verbose:
实际上也就是test这个方法的方法描述符。
常量三十六:
数一个字节查看常量类型:
往后数2个字节:
往后数13个字节:
对应于javap -verbose:
这个在之前【https://www.cnblogs.com/webor2006/p/9508341.html】也已经遇到过,主要是JDK1.6加入的,主要做校验检查的,应该是某个方法中会有它,可以查看一下jclasslib:
常量三十七:
数一个字节查看常量类型:
终于不是01了,在常量类型表中查询一下:
往后数2个字节:
指向常量池索引49,对应javap -verbose:
常量三十八:
数一个字节查看常量类型:
依然跟上一个常量类型一样,往后数2个字节看常量池索引值:
对应于60,查看javap -verbose:
常量三十九:
数一个字节查看常量类型:
往后娄2个字节:
57,对应javap -verbose:
常量四十:
数一个字节查看常量类型:
往后数2个字节:
61,对应javap -verbose:
第一次出现异常相关的信息。。
常量四十一:
数一个字节查看常量类型:
对应常量表中为:
往后数两个字节为字符串的长度:
往后再数5个字节:
对应于javap -verbose:
对应着源代码的第二个方法的名字:
常量四十二:
数一个字节查看常量类型:
又是跟上一次的常量类型一样,所以往后数2个字节:
再往后数8个字节:
对应于javap -verbose:
这是一个新的名字,是当代码中存在有静态变量相关的代码时就会有它,代表对静态代码的初始化~
常量四十三:
数一个字节查看常量类型:
往后数2个字节:
再往后数10个字节:
对应于javap -verbose:
常量四十四:
数一个字节查看常量类型:
往后数2个字节:
往后再数12个字节:
对应javap -verbose:
常量四十五:
数一个字节查看常量类型:
查找一下常量类型表,对应于:
表示名称及描述符索引信息,往后数2个字节:
索引为20,再数2个字节:
索引为21,对应javap -verbose:
常量四十六:
数一个字节查看常量类型:
又是utf的字符串,往后数2个字节:
往后数7个字节:
对应于javap -verbose:
常量四十七:
数一个字节查看常量类型:
对应于这个类型:
往后数2个字节:
索引为14、再数2个字节:
索引为15,对应一下javap -verbose:
常量四十八:
数一个字节查看常量类型:
两样的类型,往后数四个字节:
对应索引16、17,看一下javap -verbose:
常量四十九:
数一个字节查看常量类型:
往后数2个字节:
往后数24个字节:
对应于javap -verbose:
常量五十:
数一个字节查看常量类型:
对应常量类型:
往后数4个字节:
对应32、33,看下javap -verbose:
常量五十一:
数一个字节查看常量类型:
查看常量类型表:
往后数2个字节:
对应索引62,看一下javap -verbose:
常量五十二:
数一个字节查看常量类型:
查看常量表:
同样的类型,往后数四个字节:
对应javap -verbose:
常量五十三:
数一个字节查看常量类型:
往后数四个字节:
对应javap -verbose:
常量五十四:
数一个字节查看常量类型:
对应常量类型表:
往后数2个字节:
索引名为65,对应javap -verbose:
常量五十五:
数一个字节查看常量类型:
对应常量表类型:
各数两个字节:
对应于javap -verbose:
常量五十六:
数一个字节查看常量类型:
往后数2个字节:
对应索引12,所以往后数12个字节:
对应于javap -verbose:
常量五十七:
数一个字节查看常量类型:
往后数两个字节:
往后数16个字节:
对应于javap -verbose:
常量五十八:
数一个字节查看常量类型:
往后数2个字节:
对应javap -verbose:
常量五十九:
数一个字节查看常量类型:
对应常量类型表:
所以往后数四个字节:
对应于javap -verbose:
常量六十:
数一个字节查看常量类型:
往后数2个字节:
往后数16个字节:
对应于javap -verbose:
常量六十一:
数一个字节查看常量类型:
往后数2个字节:
往后数19个字节:
对应于javap -verbose:
常量六十二:
数一个字节查看常量类型:
往后数两个字节:
往后数17个字节:
对应于javap -verbose:
常量六十三:
数一个字节查看常量类型:
往后数2个字节:
往后再数7个字节:
对应于javap -verbose:
常量六十四:
数一个字节查看常量类型:
往后数2个字节:
往后再数22个字节:
对应javap -verbose:
常量六十五:
数一个字节查看常量类型:
往后数2个字节:
往后数16个字节:
对应于javap -verbose:
常量六十六:
数一个字节查看常量类型:
往后数2个字节:
往后数3个字节:
对应于javap -verbose:
常量六十七:
数一个字节查看常量类型:
往后数2个字节:
往后数21个字节:
对应于javap -verbose:
常量六十八:
数一个字节查看常量类型:
往后数2个字节:
往后数19个字节:
对应于javap -verbose:
常量六十九:
数一个字节查看常量类型:
往后数2个字节:
往后数6个字节:
对应于javap -verbose:
常量七十:
数一个字节查看常量类型:
往后数2个字节:
往后数60个字节:
对应于javap -verbose:
至此!!!完整的将字符串常量全部分析完毕,艾玛,累死了~~不过经过这么细的分析也进一步对常量池相关的规则有了更加熟练的掌握~~