我们先编写最简单的helloworld,然后用sublime打开class文件。如下:
这里我只截取部分做参考,而这段二进制文件会拿给JVM执行,不同平台,JVM会根据这些二进制文件产生不同的指令,从而实现跨平台。
这些二进制文件实际上也是按照规则排列好的,每个位置占多少字节,表示什么意思都有一定的规则,如下:
u1 u2 分别表示占一个字节,两个字节。上图中cafe占了四个字节,依次类推。_info结尾的相当于一个表,而这个表占多少内容,要查相应的表结构分析。
首先开头的cafebabe是魔数,用来表示这是Java的文件,不同的文件有不同的魔数。class文件都是相同的,接着0000 0034表示Java版本,前者表示次版本号,后者表示主版本号的十六进制表示方式,jd1.1为45,对应jdk1.8就是52(45+7)。
接下来就是比较重要的概念:001d 两个字节表示常量池的容量,0用于表示不引用任何一个常量池项目。所以我们需要减一才是总共的常量项数。根据最开始的图,我们这里接下来解析表,第一个字节表示标置,用于查找具体的表类型,对应关系如下:
于是我们可以发现我们接下来要找0a对应标志10,然后再去找10对应表的结构图。如下:
接着00 06就表示我要找的下一个常量的索引值,就这样解析完所有二进制文件后对应之间的调用关系等也相应确定下来。
实际上Javap -v 你的类名.class 就可以很方便的看到相应的引用关系:
同理我只截取部分:
当然,上面描述的不只是常量项引用关系,也有相关属性,字段,接口等等。
网友评论