文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Class文件结构之如何使用字段表与方法表

2024-04-02 19:55

关注

本篇内容主要讲解“Class文件结构之如何使用字段表与方法表”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Class文件结构之如何使用字段表与方法表”吧!

 1、字段表

字段表紧随在接口表索引之后,字段表包含访问标记、字段名索引、描述符索引、属性表,其中属性表包含属性计数器与属性集合

以这段代码为例:

package com.yang.testField;  public class Main {     private volatile int a = 1;     public static final String b = "abc";  }

16进制数据如下图所示:

Class文件结构之如何使用字段表与方法表

可以看得出,字段计数为0x0002,因为有2个字段,a和b。

字段a的访问标记是是0x0042,用这个值与标识符的特征值取与,如果结果为1,则表示该字段拥有相应的标识符。字段标识符如下所示:

Class文件结构之如何使用字段表与方法表

这里我们可以得出,a的访问标记有ACC_PRIVATE与ACC_VOLATILE。

a的名称索引为0x0005,我们看一下常量池:

Class文件结构之如何使用字段表与方法表

可以得出第一个字段的名称索引指向常量池中第5个常量项,即“a”。

a的描述符索引为0x0006,即常量池中的“I”,完成的字段类型与描述符的对照表如下:

Class文件结构之如何使用字段表与方法表

接下来是a的属性计数器,对应的值为0x0000,代表a没有属性表。

贴一下b字段表中的属性表:

Class文件结构之如何使用字段表与方法表

b的属性计数器为0x0001,代表着有属性表,属性表中只有一个元素,为0x0009,常量池中显示为ConstantValue,说明

该属性是ConstantValue类型的,属性长度为2,属性值索引为0x000A,即找到常量池中的#11,再找到#21,原来是个字符串"abc"。

为什么int a没有属性表,而static final b却有属性表?这要从字段的赋值策略说起:

对于一个实例字段,比如这里的a,赋值阶段发生在对象实例的构造方法中,即;

对于一个非final的静态字段,赋初始值会发生在解析阶段,而赋用户指定的值,会发生在初始化阶段,在类构造器方法中完成,即

对于一个final的静态字段,且是基本类型或者是String类型,在编译期间就给该变量赋予用户指定的值,并在常量池中形成一个ConstantValue类型的属性,属性值就是常量的值。如果是除去String类型以外的引用类型,那么就是在初始化阶段完成赋值操作。

下面以一个例子说明:

package com.yang.testField;  public class Main {     private volatile int a = 1;     public static final String b = "abc";     public static String c="def";     public static Thread d=new Thread();  }

方法内的情况:

Class文件结构之如何使用字段表与方法表

这里面完成的是对实例变量的赋值操作。

方法内的情况:

Class文件结构之如何使用字段表与方法表

这里面完成的是对普通静态变量c与非String的引用类型变量d的赋值操作。

更多关于对方法的理解,可以参考这篇文章java执行顺序之深入理解clinit和init

2、方法表

紧接着字段表的是方法表,方法表和字段表类似,方法表包含方法计数、访问标记、名称索引、描述符索引、属性表,其中属性表也是包含属性计数与属性集合。

方法计数、名称索引这边就不再说明了。

方法的访问标记有:

Class文件结构之如何使用字段表与方法表

这里有一个简单的例子:

package com.yang.testMethod;  public class Main {     public Main() {     }      private int getInt(int k) {         return k;     }      public static Thread getThread(int i, double d, Runnable runnable) {         System.out.println(i * d);         return new Thread(runnable);     }  }

构造方法的描述符为()V

getInt方法的描述符为(I)I

getThread方法的描述符为(IDLjava/lang/Runnable;)Ljava/lang/Thread;

从这里,我们可以看得出,方法描述符的组织方式是这样子的:(参数列表内字段的描述符)返回值的描述符

接下来讨论方法的属性表,前面说过了,属性表包含属性计数与属性集合,属性集合又包含属性名称索引+属性长度+属性值。

属性表内最主要的属性就是Code属性了,Code属性内有几个比较重要的东西:字节码、LineNumberTable行号表、LocalVariableTable局部变量表、ExceptionTable异常表

用一下的代码为例:

public static Thread getThread(int i, double d, Runnable runnable) {     try {         System.out.println(i * d);     }catch (Exception e){         return null;     }     return new Thread(runnable); }

字节码是class文件中最重要的东西了,jvm主要就是抽取字节码,然后去执行。

Class文件结构之如何使用字段表与方法表

LineNumberTable内维护着java源码与字节码之间的对应关系:

Class文件结构之如何使用字段表与方法表

LocalVariableTable内记录着局部变量描述:

Class文件结构之如何使用字段表与方法表

关于局部变量表的详细内容,可以参考我的另外一篇文章虚拟机栈的五脏六腑 。

ExceptionTable会告诉虚拟机异常的处理逻辑,比如下图的异常表,说明如果字节码从第0行到第10行出现了type类型的异常,那么将会跳转到第13行的字节码进行处理。

Class文件结构之如何使用字段表与方法表

到此,相信大家对“Class文件结构之如何使用字段表与方法表”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯