zoukankan      html  css  js  c++  java
  • 字节码访问标志与字段表详解

    在上一次【https://www.cnblogs.com/webor2006/p/9457722.html】对字节码的整体结构有了一个初步认识,回顾一下:

    下面再来看另外一个更加直观的表:

    其中需要说明的是:

    如果接口个数为0的话,那么下面的接口名则不会出现了,其它的字段、方法、附加属性都类似。

    还有一个需要说明:

    下面以结构体的形式来看一下完整的Java字节码结构,当然啦也就是跟上面的表对应的:

    下面再来补一补理论:

    Class字节码中有两种数据类型:

    • 字节数据直接量:这是基本的数据类型。共细分为u1、u2、u3、u4四种,分别代表连续的1个字节、2个字节、4个字节、8个字节组成的整体数据。
    • 表(数组):表是由多个基本数据或其它表,依照既定顺序组成的大的数据集合。表是有结构的,它的结构体现在:组成表的成分所在的位置和顺序都是已经严格定义好的。

    另外再来回顾一下常量池表:

    上面的表中描述了11种数据类型的结构,其实在JDK1.7之后又增加了3种(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)。这样一共是14种。

    字节码Access_Flag访问标志:

    好,在了解了常量池之后,接下来则是访问标志信息了,如下:

    访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明为final。而我们所定义的源代码就知道文件是类而且是public的:

    而访问标志对应字节码信息如下表:

    其中都是以"ACC"开头的。好,了解了访问标志之后,下面回到咱们的二进制文件中来往下分析,常量池之后两个字节表示访问标志,则数两个字节:

    那它到底代表什么访问标志呢,到刚才的那张英文表中去找,发现木有“0x0021”对应的标志,如下:

    其实原因是这样的:由于Java的修饰符是多种多样的,并没有穷举了每一种组合,而是每一个访问修饰符定义了一个值,那如果一个类既是public,又是final的,此时就会取这两个修饰符的并集:

    0x0011 & 0x0010 = 0x0011,所以在二进制字节码中就会记录“0x0011”,同样的,回到咱们的“0x0021”,通过查找,发现是:

    所以0x0021:是0x0020和0x0001的并集,表示ACC_PUBLIC与ACC_SUPER。表示该类是public的并能调用父类的。所以在javap -verbose中能够看到:

    紧接着访问标志之后两个字节则是当前类的类名,如下:

    所以往后数两个字节:

    注意:这是一个索引,指向常量池,所以从常量池中找一下:

    紧接着再往后两个字节则是父类类名:

    同样也在常量池中去找寻:

    紧接着父类名称之后,则是接口信息了:

    进一步展开如下:

    也就是先数两个字节来看一下接口的数量:

    表示当前类没有实现接口,既然接口数为0,则接口名则不会出现了,如下:

    字段表:

    好,两往下则是字段表信息了,如下:

    字段表用于描述类和接口中声明的变量。这里的字段包含了类级别变量以及实例变量,但是不包括方法内部声明的局部变量。

    接下来需要了解一下“字段表集合”,这是一个比较复杂的概念,虽说展开字段的信息是这样:

    但是变量表是有自己的结构的,就像常量池一看它是cp_info:

    它也是有它的结构,所以下面来看一下字段表结构:

    其中access_flags代表访问修饰符,占2个字节;name_index代表字段的名称索引,占2个字节;descriptor_index代表描述符的索引,占2个字节;这三个信息就可以完整的描述一个字段的信息;attributes_count:属性个数,可有可无;

    用结构体形式可以描述为:

    好,回到二进制文件中来分析一下字段信息,先数2个字节来看一下字段的个数:

    表示类中有一个字段,接下来得要根据字段表来看一下该字段的具体信息,首先数2个字节表示修饰符信息,如下:

    所以往后数两个字节呗:

    那它代表什么修饰符呢,上这张表去查一下:

    呃~~什么鬼,木有是0x0002的修饰符嘛,其实它是ACC_PRIVATE,只是未列在此表中,对应源代码确实是嘛:

    接下来两个字节表示字段名称索引,如下:

    那数两个字节呗:

    上常量池去查找:

    再往后两个字节则是描述符的索引:

    数两个字节:

    继续上常量池中查找:

    接下来两个字节则是属性数量,如下:

    两数2个字节:

    说明该字段木有属性信息,所以之后的attributes也不可能出现在二进制文件当中了,至此,整个字段信息就分析完了!

  • 相关阅读:
    PHP-FPM doesn't write to error log
    CSS中position属性( absolute | relative | static | fixed )详解
    微信分享踩坑
    使用layer-list实现特殊的效果
    如何正确的给ViewGroup设置OnClickListener
    android:clipchildren属性
    学习有边界吗?学了几年感觉什么也做不出,学习无用?
    电动车的蓄电池与锂电池
    《增长黑客》节选与笔记
    Firefox火狐浏览器的高效使用
  • 原文地址:https://www.cnblogs.com/webor2006/p/9457973.html
Copyright © 2011-2022 走看看