美文网首页Java高级进阶
Java字节码结构剖析三:方法表

Java字节码结构剖析三:方法表

作者: java菜 | 来源:发表于2018-11-22 14:58 被阅读0次

这里给大家介绍一款字节码分析小工具——jclasslib bytecode viewer。它可以将字节码文件结构化的展现给我们看。

紧接着上篇『字段表』的分析。后面的分析轮到了『方法表』。

方法表结构

u2 method_count:方法计数器,methods_count 的值表示当前 class 文件 methods[]数组的成员个数。

method_info methods[methods_count]: 方法表,methods[]数组中的每个成员都必须是一个 method_info 结构的数据项,用于表示当前类或接口中某个方法的完整描述。

method_info 结构:

method_info {

    u2 access_flag                     1

    u2 name_index                      1

    u2 descriptor_index                1

    u2 attribute_count                 1

    attribute_info attributes[attribute_count]

}

方法表的具体解析

知道方法表的组成结构,我们就可以直接对照着字节码文件去解析了。依然是前文用的java代码示例产生的字节码文件。紧接在『字段表』后面的16进制是0×0004=4。即该类有4个成员方法!看源代码:

publicclassMyTest2 {

    String str = "Welcome";

    privateintx = 5;

    publicstaticInteger in = 10;

    publicstaticvoidmain(String[] args) {

        MyTest2 myTest2 = newMyTest2();

        myTest2.setX(8);

        in = 20;

    }

    publicvoidsetX(intx) {

        this.x = x;

    }

}

源代码中,我们只定义了2个成员方法!但是字节码却说有4个方法。我们用jclasslib小工具打开看一下。展示如下:

这样就一目了然了,其实字节码里除了我们自己显示定义的2个方法main setX。Java编译器生成字节码的时候默认又帮我们生成了2个方法<init> 和<clinit>。

方法就是默认的构造方法。我们知道,一个类必须要有至少一个构造方法,用来完成类的实例化过程。当我们没有显示去给一个类定义一个构造方法时,Java编译器在为生成字节码文件时,会默认给它生成一个默认的构造方法。

方法是类的构造器。是类初始化阶段要执行的方法,它的职责就是为类的静态变量赋初始值(由程序员定义的那个初始值,在我们的源码中就是静态变量in的初始值10),或者如果类中有静态代码块,那就并按顺序执行静态代码块的代码。

所以,当一个类有静态变量或者静态代码块的时候,Java编译器会为这个类的字节码里生成一个<clinit>方法,在类初始化阶段去执行!

这就是为什么代码中我们只定义了2个方法,但生成的字节码里却有4个方法的原因了。

分析第一个方法。先看看方法表的部分16进制的信息,如下:从0×004开始。

首先是方法的access_flag(访问标志位),即0×0001。说明此方法是public。接着是方法的name_index(指向常量池的索引,代表方法的全限定名称),0×0011=17。我借助jclasslib小工具可以查到方法名称是<init>,就是Java编译器默认生成的构造方法。然后,是该方法的描述符信息descriptor_index,0×0012=18,同样可以查到()V。这个描述符说明我们的方法是无参的『()』。且无返回值『V』。完美符合我们构造方法的定义。

属性表分析

我们再看看它的属性个数,attributes_count的项的值表示这个方法的附加属性的数量。0×0001=1,说明这个方法只有一个附加属性。那后面就是对属性表的分析了。我们先看一下属性表的结构:

attribute_info {

    u2 attribute_name_index;

    u4 attibute_length;

    u1 info[attibute_length]

}

所以,0×0013=19。表示的就是这个属性的名字在常量池中的索引。查阅得,该属性的名字是『Code』。Code属性很重要,因为Java程序方法中的代码经过javac编译之后形成字节码存在了Code属性内。在这里,我们通过jclasslib先查看一下Code属性里有什么。

红框里的助记符就是<init>方法里要执行的代码逻辑!

Code属性

code属性的作用是保存该方法的结构,如所对应的字节码。

Code_attribute {

    u2 attribute_name_index;

    u4 attribute_length;

    u2 max_stack;

    u2 max_locals;

    u4 code_length;

    u1 code[code_length];

    u2 exception_table_length;

    {   u2 start_pc;

        u2 end_pc;

        u2 handler_pc;

        u2 catch_type;

    } exception_table[exception_table_length];

    u2 attributes_count;

    attribute_info attributes[attributes_count];

}

Java程序方法体中的代码经过Java编译处理后,最终变成字节码指令存储在Code属性中。Code属性出现在方法表的属性集合中,但是并非所有方法都有这个属性。例如接口或者类中的抽象方法就不存在Code属性。

Code属性其实是一个结构比较复杂的属性表。这里就不做过多描述,打算后面抽个时间用一篇博客来说说它。其实方法表的<init>方法到此,分析得差不多了。接下来,大家可以再对照一遍,自己去把每个方法都分析一遍,加深印象。

欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 854393687

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

相关文章

  • Java字节码结构剖析三:方法表

    这里给大家介绍一款字节码分析小工具——jclasslib bytecode viewer。它可以将字节码文件结构化...

  • 11_JVM学习笔记_字节码剖析

    字节码剖析 示例代码: 反编译信息如下: 字节码文件16进制 Java字节码结构 Class字节码中有两种数据类型...

  • Java字节码方法表

    引言 因为字段表和方法表的结构类似,所以我们直接分析Java字节码的方法表内容,理解了方法表,自然就理解了字段表 ...

  • java注解底层详解

    首先上参考文章:JAVA 注解的基本原理Java字节码方法表与属性表深度剖析这篇写的太好了,醍醐灌顶。 文章具体内...

  • Jvm基础知识下篇

    一、java执行引擎工作原理:方法调用 1.进行方法调用 Java语言的原子指令是字节码,java方法是对字节码的...

  • JVM

    JVM 基础-类字节码详解 多语言编译为字节码在 JVM 运行 Java 字节码文件-- Class文件的结构属性...

  • Jvm虚拟机原理分析性能调优

    核心技术①深入字节码底层剖析JVM内存结构②JVM垃圾收集机制与性能调优③深入理解Java内存模型JMM④深入汇编...

  • 字节码引用检测原理与实战

    一、字节码与引用检测 1.1 Java字节码 本章中的字节码重点研究Java 字节码,Java字节码(Java b...

  • java class.类结构.method

    methods 方法表与field_info中的属性表结构相同,方法里的代码,经过编译成字节码指令后,存放在方法属...

  • java字节码

      我们都知道Java字节码是JVM所使用的指令集。java字节码可以分为如下几类: 操作数栈   Java 方法...

网友评论

    本文标题:Java字节码结构剖析三:方法表

    本文链接:https://www.haomeiwen.com/subject/snelqqtx.html