`

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

阅读更多

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

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

 

本文假定读者对Java Class文件格式有一些基本的了解,建议结合相关书籍进行对照阅读。

Class文件格式信息

实例代码

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

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

魔数(magic)

类型:u4 
字节地址:00000000~00000003 
值:0xCAFEBABE

Class文件版本

次版本号(minor_version)

类型:u2 
字节地址:00000004~00000005 
值:0x0000

主版本号(major_version)

类型:u2 
字节地址:00000006~00000007 
值:0x0034

将0x0034转换为十进制,计算得到52,对应版本号为JDK 1.8。

常量池

常量池容量计数值(constant_pool_count)

类型:u2 
字节地址:00000008~00000009 
值:0x0016

将0x0016转换为十进制,计算得到22。由于容量计数是从1开始(如果没有特殊情况,通常都是从0开始),因此常量池中有21项常量,索引值范围为1~21。

常量池中每一项常量都是一个表,表开始的第一位是一个u1类型的标志位(tag)。

第1项常量

tag类型:u1 
tag字节地址:0000000A 
tag值:0x07

查表可知这个常量属于CONSTANT_Class_info结构,代表一个类或者接口的符号引用。

name_index类型:u2 
name_index字节地址:0000000B~0000000C 
name_index值:0x0002

0x0002指向了常量池中的第2项常量。

第2项常量

tag类型:u1 
tag字节地址:0000000D 
tag值:0x01

查表可知这个常量属于CONSTANT_Utf8_info结构,代表一个UTF-8编码的字符串。

length类型:u2 
length字节地址:0000000E~0000000F 
length值:0x0012

将0x0012转换为十进制,计算得到18。

bytes类型:u1 
bytes字节地址:00000010~00000021(length表明地址范围为18个字节) 
bytes值:下方图片浅蓝底对应的所有字节内容

通过WinHex查看,对应内容为chapter6/TestClass,即类的全限定名。

通过逐个字节对照ASCII字符表,我们同样可以得到内容为chapter6/TestClass。

  • 获取ASCII字符表:在Linux上执行man ascii,翻页在Tables项可以看到字符表。
  • 查找字符:先找横坐标,再找纵坐标,横竖交叉的位置即为字节对应的字符。

例如0x63为c,0x68为h,0x61为a,0x70为p,0x74为t,0x65为e,0x72为r,连起来代表单词chapter。

第3项常量

tag类型:u1 
tag字节地址:00000022 
tag值:0x07

这个常量属于CONSTANT_Class_info结构,代表一个类或者接口的符号引用。

name_index类型:u2 
name_index字节地址:00000023~00000024 
name_index值:0x0004

0x0004指向了常量池中的第4项常量。

第4项常量

tag类型:u1 
tag字节地址:00000025 
tag值:0x01

这个常量属于CONSTANT_Utf8_info结构,代表一个UTF-8编码的字符串。

length类型:u2 
length字节地址:00000026~00000027 
length值:0x0010

将0x0010转换为十进制,计算得到16。

bytes类型:u1 
bytes字节地址:00000028~00000037(length表明地址范围为16个字节) 
bytes值:下方图片浅蓝底对应的所有字节内容

通过WinHex查看,对应内容为java/lang/Object,即类的全限定名。

第5项常量

tag类型:u1 
tag字节地址:00000038 
tag值:0x01

这个常量属于CONSTANT_Utf8_info结构,代表一个UTF-8编码的字符串。

length类型:u2 
length字节地址:00000039~0000003A 
length值:0x0001

bytes类型:u1 
bytes字节地址:0000003B(length表明地址范围为1个字节) 
bytes值:0x6D

通过WinHex查看,对应内容为实例变量m。

其他常量可以通过类似的方法进行分析,但这样一个个分析确实挺辛苦的。

其实,JDK已经为我们提供了一个Class文件字节码工具:javap,可以让我们较为直观的看到Class文件的字节码内容。

执行命令:javap -verbose TestClass.class,截取常量池部分内容如下:

可以看到,版本号及前5个常量与我们分析的结果是一致的。所以,能用1行代码搞定的事儿,就不要用2行(浪费笔墨)。

常量池最后一个字节:000000D8

访问标志(access_flags)

类型:u2 
字节地址:000000D9~000000DA 
值:0x0021

查看类或接口访问标志含义表可知,该类的访问标志为ACC_PUBLIC(0x0001)、ACC_SUPER(0x0020)。

另外,通过类的定义public class TestClass,同样可以推断出类的访问标志为ACC_PUBLIC、ACC_SUPER,而ACC_INTERFACE、ACC_ENUM、ACC_FINAL、ACC_ABSTRACT、ACC_ANNOTATION、ACC_SYNTHETIC都可以排除。

所以,access_flags应该为0x0001|0x0020=0x0021,结果与查看字节码相同。

类索引(this_class)

类型:u2 
字节地址:000000DB~000000DC 
值:0x0001

this_class指向常量池的第1个常量,基于前面的分析可知:

  • 第1个常量的类型为Class,Class名称索引指向第2个常量。
  • 第2个常量类型为Utf8,对应内容为chapter6/TestClass。

因此,类索引(this_class)指向的类为chapter6/TestClass。

父类索引(super_class)

类型:u2 
字节地址:000000DD~000000DE 
值:0x0003

同样,super_class指向常量池的第3个常量。

  • 第3个常量的类型为Class,Class名称索引指向第4个常量。
  • 第4个常量类型为Utf8,对应内容为java/lang/Object。

因此,父类索引(super_class)指向的类为java/lang/Object。

接口计数器(interfaces_count)

类型:u2 
字节地址:000000DF~000000E0 
值:0x0000

接口计数器值为0,说明该类没有实现任何接口。

接口表(interfaces)

类索引(this_class)、父类索引(super_class)和接口索引(interfaces)这三项数据共同确定了当前类以及其继承关系,相关常量池内容如下:

完整地址范围:000000DB~000000E0

字段

字段计数器(fields_count)

类型:u2 
字节地址:000000E1~000000E2 
值:0x0001

说明当前类有1个字段。

字段表(fields)

访问标志(access_flags)

类型:u2 
字节地址:000000E3~000000E4 
值:0x0002

对应的访问标志为ACC_PRIVATE。

名称索引(name_index)

类型:u2 
字节地址:000000E5~000000E6 
值:0x0005

对应常量池中的第5项常量,即字段名为m。

描述符(descriptor_index)

类型:u2 
字节地址:000000E7~000000E8 
值:0x0006

对应常量池中的第6项常量,值为I,即int类型。

因此,该字段的定义为private int m;

属性计数器(attributes_count)

类型:u2 
字节地址:000000E9~000000EA 
值:0x0000

说明该字段没有属性信息。

属性表(attributes)

无。

字段完整地址范围:000000E1~000000EA

最后是方法和属性,由于内容复杂度及篇幅原因,我们下篇再续。


 

参考

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

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

 

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

 

个人公众号

二进制之路

 

0
0
分享到:
评论

相关推荐

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

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

    实例分析Java Class的文件结构

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

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

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

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

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

    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源码包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