发表文章之后,发现很多图片显示不了,请阅读我的公众号文章,以获得本文最佳体验:
本篇我们继续分析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
个人公众号
二进制之路
相关推荐
Class文件是Java编译器将源代码编译后的结果,包含了类的结构信息、方法定义、常量池等关键数据。理解并能解析Class文件,对于进行JVM优化、字节码分析、动态代理、插桩等高级技术至关重要。 首先,Class文件是以二...
总的来说,Java Class文件解析是深入理解JVM工作原理和Java程序运行机制的关键,它不仅涉及到编程实践,也是软件调试、性能优化和安全分析的重要手段。通过学习这一领域的知识,开发者能够更好地驾驭Java平台,提升...
- ProGuard和R8是常见的代码混淆工具,它们会改变class文件结构,增加逆向工程难度。 4. **代码优化**: - 通过分析class文件,可以了解方法调用频率、变量使用情况,从而进行针对性优化。 - 使用ProGuard/R8...
本项目“基于Go的Java Class文件解析工具”旨在利用Go语言开发一个工具,用于解析和理解这些二进制文件,帮助开发者更好地分析和理解Java程序的底层结构。 Go语言是一种静态类型的、编译型的、垃圾回收的语言,具有...
通过以上分析,我们可以看到,class文件解析是理解Java运行机制的关键一环,而《深入理解Java虚拟机》一书为我们提供了宝贵的理论基础和实践指导。结合样例数据,读者可以进一步探索和掌握Java虚拟机的内部运作。
1. **Java类文件结构**:首先,了解Java类文件的内部结构至关重要。每个Java类文件都是以`.class`后缀的二进制文件,它由魔数、版本号、常量池、访问标志、类索引、父类索引、接口索引集合、字段表集合、方法表集合...
1. 创建`ClassWriter`实例,并设定类的访问标志、全限定名和父类信息(通常是`java.lang.Object`)。 2. 定义代理类的字段,如果需要的话。 3. 为每个要拦截的方法创建一个`MethodVisitor`。在`visitMethod`方法中...
Java 类文件结构是Java虚拟机(JVM)执行的基础,它包含了构成Java程序的所有必要信息。Class文件是一种二进制...理解Class文件的结构对于深入学习Java虚拟机的工作原理、优化代码以及进行反编译分析等都有重要意义。
Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...
例如,将常量池、字段表和方法表等结构抽象为树节点,通过递归遍历这些节点来处理和分析Class文件内容。这种实现方式有助于理解复杂的类结构,并方便进行修改和优化。 在Java开发中,理解Class文件的结构对于深入...
### 安卓反编译dex文件格式实例分析 #### 第一部分:创造一个可供分析的Hello.dex ##### 测试环境 为了进行本次实验,我们需要搭建一个可靠的测试环境。本实验使用了以下配置: - **操作系统**: Ubuntu 12.04 64...
#### 一、Java与JVM中的Class文件加载机制概述 Java作为一种动态性极强的解释型编程语言,在程序运行时,Java虚拟机(JVM)负责将编译生成的`.class`文件加载到内存中进行执行。在Java环境中,每个类(Class)以及...
另外,` jclasslib`是一款可视化的字节码查看器,它提供了更直观的方式查看和分析.class文件,包括类结构、常量池、字段和方法的详细信息。使用这样的工具可以帮助我们更好地理解JVM的内部工作原理。 此外,学习...
6. **代码生成**:最后,将AST转换回字节码,即.class文件,这一步由Java编译器完成。字节码是Java虚拟机(JVM)能执行的语言。 在这个实例程序中,可能包含以下组件: - 一个词法分析器,用于将源代码分割成标记。 ...
本压缩包文件提供了两个示例项目,分别展示了JDK动态代理和CGLib动态代理的实现,帮助我们理解这两种技术的工作原理以及它们生成的class文件结构。 首先,我们来详细了解JDK动态代理。JDK动态代理基于Java的接口...
Java字节码是Java程序编译后的产物,它以`.class`文件的形式存在,是Java虚拟机(JVM)能够理解和执行的二进制代码。本文将深入解析Java字节码的格式,帮助你理解其背后的运行机制。 1. **Java字节码结构** Java...
### Java程序结构与示例分析 #### 一、概述 Java是一种广泛使用的面向对象编程语言,具有简单性、面向对象性、健壮性、安全性、平台独立性等优点。Java程序的基本单位是类(Class),类由方法和成员变量组成。本文...
它包含了编译后的.class文件和其他资源,用户可以通过java -jar命令直接运行。 7. **安全性**:文件传输可能涉及安全问题,如数据的加密和身份验证。Java提供了SSL/TLS协议支持,可以使用SSLSocket和...