Java Class类文件结构

【深入Java虚拟机】之二:Class类文件结构 Java是与平台无关的语言,这得益于Java源代码编译后生成的存储字节码的文件,即Class文件,以及Java虚拟机的实现。不仅使用Java编译器可以把Java代码编译成存储字节码的Class文件,使用JRuby等其他语言的编译器也可以把程序代码编译成Class文件,虚拟机并不关心Class的来源是什么语言,只要它符合一定的结构,就可以在Java中运行。Java语言中的各种变量、关键字和运算符的语义最终都是由多条字节码命令组合而成的,因此字节码命令所能提供的语义描述能力肯定会比Java语言本身更强大,这便为 阅读详情

感谢原作者:  http://blog.youkuaiyun.com/zhy05/article/details/1800309


Class文件格式

Class文件格式ClassFile结构体的C语言描述如下:

struct ClassFile

{

              u4 magic;                                 //识别Class文件格式,具体值为0xCAFEBABE,

              u2 minor_version;            // Class文件格式副版本号,

              u2 major_version;            // Class文件格式主版本号,

              u2 constant_pool_count; //  常数表项个数,

              cp_info **constant_pool;// 常数表,又称变长符号表,

              u2 access_flags;               //Class的声明中使用的修饰符掩码,

              u2 this_class;                   //常数表索引,索引内保存类名或接口名,

              u2 super_class;                //常数表索引,索引内保存父类名,

              u2 interfaces_count;        //超接口个数,

              u2 *interfaces;                 //常数表索引,各超接口名称,

              u2 fields_count;       //类的域个数,

              field_info **fields;          //域数据,包括属性名称索引,

//域修饰符掩码等,

              u2 methods_count;          //方法个数,

              method_info **methods;//方法数据,包括方法名称索引,方法修饰符掩码等,

              u2 attributes_count;        //类附加属性个数,

              attribute_info **attributes; //类附加属性数据,包括源文件名等。

};

 

其中u2为unsigned short,u4为unsigned long:

typedef unsigned char   u1;

typedef unsigned short  u2;

typedef unsigned long   u4;

 

cp_info **constant_pool是常量表的指针数组,指针数组个数为constant_pool_count,结构体cp_info为

struct cp_info

{

              u1 tag;       //常数表数据类型

              u1 *info;   //常数表数据

};

常数表数据类型Tag定义如下:

#define CONSTANT_Class                                         7     

#define CONSTANT_Fieldref                                     9

#define CONSTANT_Methodref                                10

#define CONSTANT_InterfaceMethodref                  11

#define CONSTANT_String                                                      8

#define CONSTANT_Integer                                                  3

#define CONSTANT_Float                                                       4

#define CONSTANT_Long                                                       5

#define CONSTANT_Double                                      6

#define CONSTANT_NameAndType                         12

#define CONSTANT_Utf8                                                        1

每种类型对应一个结构体保存该类型数据,例如CONSTANT_Class 的info指针指向的数据类型应为CONSTANT_Class_info

struct CONSTANT_Class_info

{

              u1 tag;

              u2 name_index;

};

图2

CONSTANT_Utf8的info指针指向的数据类型应为CONSTANT_Utf8_info

struct CONSTANT_Utf8_info

{

              u1 tag;

              u2 length;

              u1 *bytes;

};

Tag和info的详细说明参考《Java虚拟机规范》第四章4.4节。

access_flags为类修饰符掩码,域与方法都有各自的修饰符掩码。

#define ACC_PUBLIC                                0x0001 

#define ACC_PRIVATE                             0x0002

#define ACC_PROTECTED                                   0x0004

#define ACC_STATIC                                0x0008

#define ACC_FINAL                                              0x0010

#define ACC_SYNCHRONIZED                         0x0020

#define ACC_SUPER                                                0x0020

#define ACC_VOLATILE                                        0x0040

#define ACC_TRANSIENT                                      0x0080 

#define ACC_NATIVE                               0x0100

#define ACC_INTERFACE                                      0x0200 

#define ACC_ABSTRACT                                       0x0400 

#define ACC_STRICT                                      0x0800

例如类的修饰符为public abstract则access_flags的值为ACC_PUBLIC | ACC_ABSTRACT=0x0401。

this_class的值是常数表的索引,索引的info内保存类或接口名。例如类名为com.sum.java.swing.SwingUtitlities2在info保存为com/sum/java/swing/SwingUtitlities2

super_class的值是常数表的索引,索引的info内保存超类名,在info内保存形式和类名相同。

interfaces是数组,数组个数为interfaces_count,数组内的元素为常数表的索引,索引的info内保存超接口名,在info内保存形式和类名相同。

field_info **fields是类域数据的指针数组,指针数组个数为fields_count,结构体field_info定义如下:

struct field_info

{

              u2 access_flags;                 //域修饰符掩码

              u2 name_index;                 //域名在常数表内的索引

              u2 descriptor_index;          //域的描述符,其值是常数表内的索引

              u2 attributes_count;           //域的属性个数

              attribute_info **attributes; //域的属性数据,即域的值

 

};

例如一个域定义如下:

private final static byte UNSET=127;

则该域的修饰符掩码值为:ACC_PRIVATE | ACC_STATIC | ACC_FINAL=0x001A

常数表内name_index索引内保存数据为UNSET,常数表内descriptor_index索引内保存的数据为B(B表示byte, 其他类型参考《Java虚拟机规范》第四章4.3.2节)。attributes_count的值为1,其中attributes是指针数组。指针数组个数为attributes_count,在此为1,attribute_info结构体如下:

struct attribute_info

{

              u2 attribute_name_index;   //常数表内索引

              u4 attribute_length;            //属性长度

              u1 *info;                             //根据属性类型不同而值不同

}; 

attribute_info可以转换(cast)为多种类型ConstantValue_attribute,Exceptions_attribute,LineNumberTable_attribute,LocalVariableTable_attribute,Code_attribute等。

因为域的属性只有一种:ConstantValue_attribute,因此此结构体转换为

struct ConstantValue_attribute

{

              u2 attribute_name_index;        //常数表内索引

              u4 attribute_length;                 //属性长度值,永远为2

              u2 constantvalue_index;         //常数表内索引,保存域的值

//在此例中,常数表内保存的值为127

};

method_info **methods是方法数据的指针数组,指针数组个数为methods_count,结构体method_info定义如下:

struct method_info

{

              u2 access_flags;                   //方法修饰符掩码

              u2 name_index;                   //方法名在常数表内的索引

              u2 descriptor_index;            //方法描述符,其值是常数表内的索引

              u2 attributes_count;             //方法的属性个数

              attribute_info **attributes;  //方法的属性数据,

//保存方法实现的Bytecode和异常处理

};

例如一个方法定义如下:

public static boolean canAccessSystemClipboard(){

              ...

}

则access_flags的值为 ACC_PUBLIC | ACC_STATIC =0x0009,常数表内name_index索引内保存数据为canAccessSystemClipboard,常数表内descriptor_index索引内保存数据为()Z;(括号表示方法参数,Z表示返回值为布尔型,详细说明参照《Java虚拟机规范》第四章4.3.2节)。attribute_info **attributes是方法的属性指针数组,个数为attributes_count,数组内保存的是常数表索引,info为Code_attribute或Exceptions_attribute。

本文不解析方法内容,因此忽略Code_attribute和Exceptions_attribute的内容。

 

ClassFile结构体中的attribute_info **attributes是附加属性数组指针,个数为attributes_count,本文只识别SourceFile属性。

struct SourceFile_attribute

{

              u2 attribute_name_index; //常数表内索引

              u4 attribute_length;          //属性长度值,永远为2

              u2 sourcefile_index;         //常数表内索引,info保存源文件名

};

例如com.sum.java.swing.SwingUtitlities2类的源文件名为SwingUtitlities2.java。

              以上是本文需要解析的Class文件格式。

2.1.2 读取数据

定义CJavaClass类完成解析Class文件,生成Java源程序字符串。使用VC++的MFC类CFile从Class文件读取数据。例如:用16进制编辑器打开Class文件,如图3,前4个byte分别是CA FE BA BE,使用CFile::Read(tmp,sizeof(u4))读取后,tmp的值为0xBEBAFECA,所以需要位转换。定义以下方法从文件读取定长数据:

                            void readu1(u1 *buff);

  void readu2(u2 *buff);

  void readu4(u4 *buff);

定义如下方法读取变长数据。

void readun(void *buff,u4 len);

读取的u2和u4的数据需要位转换:

U1  [0]

U1 [1]

U1   [1]

U1 [0]

U2:

U1  [0]

U1 [1]

U1   [3]

U4:

U1 [2]

U1  [3]

U1 [2]

U1   [0]

U1 [1]

调用void readu4(u4 *buff);后buff的值为0xCAFEBABE,该值为ClassFile的magic,识别该文件是Java Class文件。

图3

              magic的后面是Class格式的版本号,图3的版本为0x00000030=0.48。版本后面是常数表的元素个数,图3的常数表的元素个数为0xD2=210个。常数表的元素个数之后如ClassFile结构体定义的常数表,类信息,接口信息,域信息,方法信息和附加属性等。

2.2 生成Java源文件

              解析Class文件后,生产ClassFile结构体。遍历该结构体数据,则可根据Java语言规范生成Java源文件。例如根据ClassFile的access_flags值获得Java类的修饰符,其中access是CArray<CString,CString&>,保存类所有的修饰符:

              if((flag & ACC_PUBLIC )==ACC_PUBLIC)

              {

                                          access.Add(CString("public"));

              }

              if((flag & ACC_PRIVATE)==ACC_PRIVATE)

              {

                                          access.Add(CString("private"));

 

              }

              if((flag & ACC_PROTECTED)==ACC_PROTECTED)

              {

                                          access.Add(CString("protected"));

 

              }

…

2.3显示视图

              将获得的Java源代码显示在MFC的CScrollView视图非常简单,可以添加一些关键字颜色,例如注释显示为草绿色等,如图4。

图4

【java】详解Java的类文件(class文件)结构 1.概述 转载:详解Java的类文件(class文件)结构 大家好,我是二哥呀,今天我拿了一把小刀,准备解剖一下 Java 的 class 文件。 CS 的世界里流行着这么一句话,“计算机科学领域的任何问题都可以通过增加一个中间层来解决”。对于 Java 来说,JVM 就是这么一个产物,“Write once, Run anywhere”之所以能实现,靠得就是 JVM,它能在不同的操作系统下运行同一份源代码编译后的 class 文件。 Java 是跨平台的,JVM 作为中间层,自然要针对不同的操作系统提. 阅读详情

相关推荐

告别拼音!用VSCode+Dosbox-X搞定汇编语言课程设计里的中文姓名显示

本文详细介绍了如何利用VSCode和Dosbox-X解决汇编语言课程设计中中文姓名显示的问题。通过配置开发环境、理解GB2312编码及正确使用汇编指令,学生可以告别拼音显示,实现中文字符的正确输出。文章还提供了完整的代码示例和常见问题排查方法,帮助读者快速掌握这一实用技能。

weixin_30872337的博客 425

.class文件格式(java字节码文件的格式)

一个.class文件对应一个类(Class) 包含虚拟机指令

tuhuolong的专栏 2441

UniApp X 网络请求避坑指南:从 JS 到 UTS 的 JSON 数据处理全解析

摘要:UniAppX开发中处理JSON数据时,UTS强类型特性要求开发者改变JS习惯。本文对比两种主流方案:1)UTSJSONObject通过keypath访问数据,兼容JS但缺乏类型提示;2)type+泛型方案,通过定义数据类型实现强类型校验和智能提示,推荐用于固定数据结构。文章详细演示了两种方式的具体实现、转换方法及实战案例,并提供了类型定义技巧和注意事项,帮助开发者编写更稳定高效的跨平台应用。

归梦工作室 2789

class文件格式解析

当我们写个开发一个java程序后,通过通过javac(编译工具)将其编译成.class格式的字节码文件,在交给JVM通过字节码解释器或JIT即时编辑器混合执行,class文件其实就是一个二进制字节流文件,他有固定的格式。下面我们来详细介绍一个class文件的格式与组成。

po29905的博客 1063

告别安装烦恼!Orange3 3.38.0 Windows绿色版下载即用,附保姆级汉化与组件配置指南

本文详细介绍了Orange3 3.38.0 Windows绿色版的下载与使用,包括中文汉化、组件配置及高效管理技巧。这款无需安装的数据科学工具特别适合快速验证想法的研究人员和移动办公用户,支持多种数据源和可视化工具,大幅提升工作效率。

weixin_30897233的博客 600

3.1 计算机视觉的发展和卷积神经网络概要(百度架构师手把手带你零基础实践深度学习原版笔记系列)

3.1 计算机视觉的发展和卷积神经网络(百度架构师手把手带你零基础实践深度学习原版笔记系列) 概要 计算机视觉作为一门让机器学会如何去“看”的科学学科,具体的说,就是让机器去识别摄像机拍摄的图片或视频中的物体,检测出物体所在的位置,并对目标物体进行跟踪,从而理解并描述出图片或视频里的场景和故事,以此来模拟人脑视觉系统。因此,计算机视觉也通常被叫做机器视觉,其目的是建立能够从图像或者视频中“感知”信息的人工系统。 计算机视觉技术经过几十年的发展,已经在交通(车牌识别、道路违章抓拍)、安防(人脸闸机.

aiAI 691

Java字节码.class文件案例分析

我是个懒人,平时都不太喜欢写点东西,大部分时间都是自己一个人在琢磨,被同事给了个外号叫:“码疯”;很少泡在优快云的Blog中,也只是偶尔想起来了写点东西过来玩玩,大部分时间都习惯了一个人享受午后阳光下的阅卷、享受半夜灯光中的码战。慢慢地反而习惯了一种生活,让自己心里得激情沉浸在无忧无虑的生活中,大部分时间则是真正在享受代码带来的生活的快感。这篇东西是周末忙里偷闲用Markdown整理的,记录下来分享给大家,希望有所价值。

风中的索莉逖亚 9612

告别时钟树平衡噩梦:在Innovus中巧妙设置stop/ignore pin来优化分段时钟网络

本文深入探讨了在Innovus工具中利用stop/ignore pin优化分段时钟树网络的高阶技巧。针对数字IC后端设计中的时钟树平衡难题,详细解析了特殊引脚属性的战略应用场景和配置方法,帮助工程师有效解决SoC设计中复杂的时钟结构问题,显著提升时序收敛效率。

weixin_30836759的博客 288

一文理解Java-class字节码文件

前言 java语言在其刚诞生之际喊出的口号–“Write Once,Run Anywhere”,正是基于字节码(byte code)而存在的,java能够做到平台无关性,得力于这样一款优秀的中间语言,字节码的描述能力比java更强,所以它当然还不止为java服务,它同样为运行于JVM的其他语言服务,以作为一款通用的,与平台无关的,交付给JVM执行的媒介 广义的class文件就是字节码,但字节码不仅仅是class文件,它作为一段二进制流,还可以以其他各种形式存在,如压缩包(jar)、网络流等等 Tips:理论

b1ackc4t的博客 1530

ESP32设备驱动-TM1637-驱动4位7段数码管

TM1637是一款带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成了MCU数字接口、数据锁存、LED高压驱动、键盘扫描等功能。 TM1637使用DIP20/SOP20封装,主要适用于电磁炉、微波炉、小家电的显示驱动。

视觉与物联智能 2117

SAP-ABAP:FI财务会计模块常用BAPI及核心用途实例说明

SAP FI模块的BAPI覆盖了从主数据管理、凭证过账到财务关账的全流程操作,是系统集成与自动化的重要工具。实际应用中需结合业务场景选择合适的BAPI,并严格遵循事务控制与校验规则。如需扩展功能,可通过BAdI或用户出口增强标准逻辑。

baidu_35680696的博客 1601

Java class文件格式

本文的主要内容是了解Java类、方法、成员变量在class文件中的存储方式,以及class文件中的常量池内容。Java字节码的格式是严格限定的

YANYONG_的博客 407

Couldn‘t agree a key exchange algorithm(available:curve25519-sha256,curve25519-sha256@libssh.org解决方案

本文主要介绍了Couldn’t agree a key exchange algorithm(available:curve25519-sha256,curve25519-sha256@libssh.org解决方案,希望能对使用winscp的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案 2.1 方案一 2.2 方案二

weixin_43178406的博客 4万+

Java Class类文件结构

本文详细介绍了Java类文件结构,学习本文内容,您将掌握Java类文件的基本概念、类文件的结构、类文件的内容结构、类文件的常量池、类文件的访问标记、类索引、父类索引和接口索引、字段表、方法表、属性表、属性表的结构、属性表的类型、属性表的使用场景、属性表的使用方法、属性表的使用示例、属性表的使用注意事项,为您的Java编程之旅打下坚实基础。 本文准备带大家解剖一下 Java 的类文件结构,也就是 .class 文件的内容结构,虽然它实际上是一串连续的二进制,由 0 和 1 组成,但我们仍然可以借助一些工具来

在技术的广袤天地里,本博客如精准罗盘。剖析前沿科技,深掘代码奥秘,以精炼笔触,带您穿越复杂技术迷宫,速达知识彼岸。 2015

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【Java】三、Class 类文件结构

Class 类文件结构 平台无关性 Java 是与平台无关的语言,这得益于 Java 源代码编译后生成的存储字节码的文件,即 Class 文件,以及 Java 虚拟机的实现。不仅使用 Java 编译器可以把 Java 代码编译成存储字节码的 Class 文件,使用 JRuby 等其他语言的编译器也可以把程序代码编译成 Class 文件,虚拟机并不关心 Class 的来源是什么语言,只要它符...

qwertyuiopasdfghjklzxcvbnm 527

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

详解Java的类文件结构(.class文件的结构)

通过 jclasslib 看一下它当中一个很重要的属性——Code, 方法的关键信息都存储在里面。1)对于基本数据类型来说,使用一个字符来表示,比如说 I 对应的是 int,B 对应的是 byte。在Java类文件中,常量池是一个索引表,它从索引值1开始计数,每个条目都有一个唯一的索引。评论区有读者问到:“怎么通过索引值,定位到在class 文件中的位置,这个是咋算的?方法表和字段表类似,区别是用来存储方法的信息,包括方法名,方法的参数,方法的签名。我画了一副图,可以完整的表示字段的结构,包含属性表在内。

sunyan5211314的博客 1300

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

java class类文件结构

平台无关性     Java是与平台无关的语言,这得益于Java源代码编译后生成的存储字节码的文件,即Class文件,以及Java虚拟机的实现。不仅使用Java编译器可以把Java代码编译成存储字节码的Class文件,使用JRuby等其他语言的编译器也可以把程序代码编译成Class文件,虚拟机并不关心Class的来源是什么语言,只要它符合一定的结构,就可以在Java中运行。Java语言中的各种变量...

GarfieldEr007的专栏 721

Java Class类文件结构分析

Java的.Class类文件结构分析 序言:JVM 把我们的.java文件编译为.Class文件,本文只要分析 ①反汇编Class文件后对应的java字节码指令 ②Class文件的文件结构(使用工具WinHex查看) 第一步: 我们先写一个简单的.java程序(本文已Test02.java为例进行简单分析) Test02.java代码如何: 运行Test02.java后得到.class文件 第...

qq_37213846的博客 331

java中class类文件结构

类文件是java程序编译后产生的文件,要了解java虚拟机,了解它的类文件结构是必不可少的。 类文件简介 首先我们要清楚java的class类文件是以8字节为基础的二进制流,什么叫以8位字节为基础,就是如果你是16,32位或者以上的东西,它都会分割开来存储的,而且每个数据之间没有任何的分割符号,像一家人一样紧凑的挨在一起。 这种文件中包含了虚拟机指令集,符号表还有一些辅助信息。它的数据类型只有...

weixin_43272605的博客 428

Java Class类文件的结构

基础概念 任何一个 Class 文件都对应着唯一的一个类或接口的信息 Class 文件是一组以字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符。这使得整个 Class 文件中存储的内容几乎全部是 程序运行的必要数据 Class 文件格式采用一种类似于 C 语言结构体的伪结构来存储数据,这种伪结构只有“无符号数” 和 “表”两种数据类型 无符号数 无符号数属于基本的数据类型,以 u1,u2,u4,u8 来分别代表 1 个字节、2 个字节、4 个字节、8.

wgxaaa的博客 1373

java Class类文件的结构

Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部都是程序运行的必要数据,没有空隙存在。当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前方式侵害成若干个8位字节时行存储。如下所示: package jvm; public class BigObject { pu...

qq_37209855的博客 234

JAVA Class类文件结构

文章目录前言一、魔数与Class文件的版本1.魔数2.文件版本号 前言 Class文件是一组以8个字节为进出单位的二进制流,各个数据项目严格按照顺序紧凑的排列在文件中,中间没有任何的分隔符。当遇到占用8个字节以上空间数据项时,则会按照高位在前的方式进行分割成若干个8字节进行存储。Java文件格式采用一种类似C语言结构体的伪结构来存储数据,这种伪结构只有两种数据类型:“无符号数”和“表”。 无符号数属于基本的结构类型,以u1、u2、u4、u8来分别标识1字节、2字节、4字节和8字节的无符号数,无符号数可以

记得我雨的博客 512
上一篇: JDK工具之 jps命令
下一篇: JDK和adb的环境变量配置
NewJerryj
博客等级 码龄19年 196粉丝 115原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值