`

Java Class文件结构实例分析(下)

阅读更多

发表文章之后,发现很多图片显示不了,请阅读我的公众号文章,以获得本文最佳体验:

Java Class文件结构实例分析(下)

 

本篇我们继续分析Class文件结构的方法及属性部分内容,上节内容回顾请查看:

Java Class文件结构实例分析(上)

Class文件格式信息

继续上节实例代码

package chapter6;
public class TestClass {
    private int m;
    public int inc() {
        return m + 1;
    }
}

使用JDK1.8编译成class文件,然后通过WinHex打开

方法

上节我们分析到字段部分,字段的完整地址范围:000000E1~000000EA。

跟在字段后面的是方法,下面继续分析。

方法计数器(methods_count)

类型:u2 
字节地址:000000EB~000000EC 
值:0x0002

说明当前类有2个方法。

第1个方法

访问标志(access_flags)

类型:u2 
字节地址:000000ED~000000EE 
值:0x0001

查表得到对应的访问标志为ACC_PUBLIC。

名称索引(name_index)

类型:u2 
字节地址:000000EF~000000F0 
值:0x0007

对应常量池中的第7项常量,值为<init>,即实例初始化方法。

描述符(descriptor_index)

类型:u2 
字节地址:000000F1~000000F2 
值:0x0008

对应常量池中的第8项常量,值为()V,说明该方法无参数,返回类型为void。

由前3项可知,第1个方法为类的实例初始化方法。

属性计数器(attributes_count)

类型:u2 
字节地址:000000F3~000000F4 
值:0x0001

说明该字段有1个属性。

属性的通用格式如下:

第1个属性

名称索引(attribute_name_index)

类型:u2 
字节地址:000000F5~000000F6 
值:0x0009

对应常量池中的第9项常量,值为Code。

属性值的长度(attribute_length)

类型:u4 
字节地址:000000F7~000000FA 
值:0x0000002F

将0x0000002F转换为十进制,计算得到47。

操作数栈的最大深度(max_stack)

类型:u2 
字节地址:000000FB~000000FC 
值:0x0001

即最大深度为1。操作数栈的最大深度,由编译期决定。

局部变量的个数(max_locals)

类型:u2 
字节地址:000000FD~000000FE 
值:0x0001

即局部变量的个数为1。局部变量的个数,由编译期决定。

max_locals的单位是Slot,Slot是虚拟机为局部变量分配内存所使用的最小单位。对于长度不超过32位的数据类型,每个局部变量占用1个Slot。而double和long的数据类型长度为64位,需要占用两个Slot。

code[]数组的字节数(code_length)

类型:u4 
字节地址:000000FF~00000102 
值:0x00000005

字节码指令(code)

类型:u1 
长度/字节数:5 
字节地址:00000103~00000107

其中,第0、1、4字节为字节码指令,第2、3字节为参数索引。

常量池

实例初始化方法字节码指令信息

其中,初始化方法是没有参数的,但args_size为1。这其实是因为对于非static方法,编译器默认会将指向当前对象的this作为方法的第一个参数,以便在调用方法的时候使用。

异常表长度(exception_table_length)

类型:u2 
字节地址:00000108~00000109 
值:0x0000

说明没有异常表信息。

异常表(exception_table)

属性计数器(attributes_count)

类型:u2 
字节地址:0000010A~0000010B 
值:0x0002

说明该字段有2个属性。

第1个方法Code属性的第1个属性

名称索引(attribute_name_index)

类型:u2 
字节地址:0000010C~0000010D 
值:0x000C

对应常量池中的第12项常量,值为LineNumberTable,即字节码与源码的行号信息。

LineNumberTable属性值的长度(attribute_length)

类型:u4 
字节地址:0000010E~00000111 
值:0x00000006

LineNumberTable行号表的长度(line_number_table_length)

类型:u2 
字节地址:00000112~00000113 
值:0x0001

字节码与源码行号(字节地址:00000114~00000117)

第1个方法Code属性的第2个属性

名称索引(attribute_name_index)

类型:u2 
字节地址:00000118~00000119 
值:0x000D

对应常量池中的第13项常量,值为LocalVariableTable,即方法的本地变量表信息。

LocalVariableTable属性值的长度(attribute_length)

类型:u4 
字节地址:0000011A~0000011D 
值:0x0000000C

将0x0000000C转换为十进制,计算得到12。

LocalVariableTable局部变量表的长度(local_variable_table_length)

类型:u2 
字节地址:0000011E~0000011F 
值:0x0001

LocalVariableTable第1个局部变量(字节地址:00000120~00000129)

start_pc和length两者结合起来就是这个局部变量在字节码之中的作用域范围。

也就是说,这个局部变量为this,类型为chapter6/TestClass,存放在局部变量表的第0个Slot,作用域为code[0]~code[4]。

第1个方法对应的字节内容

第2个方法

访问标志(access_flags)

类型:u2 
字节地址:0000012A~0000012B 
值:0x0001

查表得到对应的访问标志为ACC_PUBLIC。

名称索引(name_index)

类型:u2 
字节地址:0000012C~0000012D 
值:0x0010

对应常量池中的第16项常量,值为inc,正是我们定义的实例方法名。

描述符(descriptor_index)

类型:u2 
字节地址:0000012E~0000012F 
值:0x0011

对应常量池中的第17项常量,值为()I,说明该方法无参数,返回类型为int。

以上3项,说明该方法定义为public int inc()。

属性计数器(attributes_count)

类型:u2 
字节地址:00000130~00000131 
值:0x0001

说明该字段有1个属性。

第1个属性

名称索引(attribute_name_index)

类型:u2 
字节地址:00000132~00000133 
值:0x0009

对应常量池中的第9项常量,值为Code。

Code属性值的长度(attribute_length)

类型:u4 
字节地址:00000134~00000137 
值:0x00000031

将0x00000031转换为十进制,计算得到49。

Code操作数栈的最大深度(max_stack)

类型:u2 
字节地址:00000138~00000139 
值:0x0002

即最大深度为2。

Code局部变量的个数(max_locals)

类型:u2 
字节地址:0000013A~0000013B 
值:0x0001

即局部变量的个数为1。

code[]数组的字节数(code_length)

类型:u4 
字节地址:0000013C~0000013F 
值:0x00000007

Code字节码指令(code)

类型:u1 
长度/字节数:7 
字节地址:00000140~00000146

其中,第0、1、4、5、6字节为字节码指令,第2、3字节为参数索引。

常量池

实例初始化方法字节码指令信息

Code异常表长度(exception_table_length)

类型:u2 
字节地址:00000147~00000148 
值:0x0000

说明没有异常表信息。

Code异常表(exception_table)

Code属性计数器(attributes_count)

类型:u2 
字节地址:00000149~0000014A 
值:0x0002

说明该字段有2个属性。

第2个方法Code属性的第1个属性

名称索引(attribute_name_index)

类型:u2 
字节地址:0000014B~0000014C 
值:0x000C

对应常量池中的第12项常量,值为LineNumberTable。

值为LineNumberTable属性值的长度(attribute_length)

类型:u4 
字节地址:0000014D~00000150 
值:0x00000006

值为LineNumberTable行号表的长度(line_number_table_length)

类型:u2 
字节地址:00000151~00000152 
值:0x0001

字节码与源码行号(字节地址:00000153~00000156)

第2个方法Code属性的第2个属性

名称索引(attribute_name_index)

类型:u2 
字节地址:00000157~00000158 
值:0x000D

对应常量池中的第13项常量,值为LocalVariableTable。

LocalVariableTable属性值的长度(attribute_length)

类型:u4 
字节地址:00000159~0000015C 
值:0x0000000C

将0x0000000C转换为十进制,计算得到12。

LocalVariableTable局部变量表的长度(local_variable_table_length)

类型:u2 
字节地址:0000015D~0000015E 
值:0x0001

LocalVariableTable第1个局部变量(字节地址:0000015F~00000168)

start_pc和length两者结合起来就是这个局部变量在字节码之中的作用域范围。

也就是说,这个局部变量为this,类型为chapter6/TestClass,存放在局部变量表的第0个Slot,作用域为code[0]~code[6]。

第2个方法对应的字节内容

类的属性计数器(attributes_count)

类型:u2 
字节地址:00000169~0000016A 
值:0x0001

说明该类有1个属性。

第1个属性

名称索引(attribute_name_index)

类型:u2 
字节地址:0000016B~0000016C 
值:0x0014

对应常量池中的第12项常量,值为SourceFile,即class文件的Java源文件名称。

属性值的长度(attribute_length)

类型:u4 
字节地址:0000016D~00000170 
值:0x00000002

类的源文件名称索引(sourcefile_index)

类型:u2 
字节地址:00000171~00000172 
值:0x0015

对应常量池中的第21项常量,值为TestClass.java。

字节码内容


 

参考

《Java虚拟机规范》(Java SE 8版)

《深入理解Java虚拟机 JVM高级特性与最佳实践》

 

转载请注明来源:http://zhanjia.iteye.com/blog/2430257

 

个人公众号

二进制之路

 

0
0
分享到:
评论

相关推荐

    Java Class文件的结构分析及其解析执行.pdf

    java Class文件分析及其解析执行是分析JVM的重要部分,通过实例对Class文件的结构进行了详细分析,并初步实现了Class文件的解析执行。

    实例分析Java Class的文件结构

    今天把之前在Evernote中的笔记重新整理了一下,发上来供对java class 文件结构的有兴趣的同学参考一下

    java源码包---java 源码 大量 实例

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    JAVA上百实例源码以及开源项目源代码

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    安卓反编译dex文件格式实例分析

    内容的目录结构如下 : 第一部分:创造一个可供分析的 Hello.dex 1. 测试环境 2. java 源码和编译方法 3. 使用 ADB 运行测试 4. 重要说明第二部分:分析过程 1. dex 整个文件的布局 2. header 3. string_ids 4. ...

    JAVA上百实例源码以及开源项目

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    java源码包4

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    java源码包3

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    java源码包2

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java编写的网页版魔方游戏 内容索引:JAVA源码,游戏娱乐,魔方,网页游戏 Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    Java编写的网页版魔方游戏 内容索引:JAVA源码,游戏娱乐,魔方,网页游戏 Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分...

    java开源包8

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包6

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包9

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包11

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包4

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包101

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包5

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

Global site tag (gtag.js) - Google Analytics