`
cgaolei
  • 浏览: 58500 次
  • 性别: Icon_minigender_1
  • 来自: 长春
社区版块
存档分类
最新评论

Java类文件格式快速入门

阅读更多

原文地址:http://viralpatel.net/blogs/2009/01/tutorial-java-class-file-format-revealed.html

原作者:Viral Patel

译者:Alan Gao @ cgaolei.iteye.com

 

译者序:

最近工作解决一个问题时需要用到Java bytecode的知识,临阵磨枪学习了一下,还真的对java bytecode产生的很大的兴趣,打算平时再深入研究一下。学字节码时,我是先从类文件的格式入手的。当然,学习这方面东西,最权威不过的还得是<<Java虚拟机规范了>>:http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html。 只不过那里写的过于正规详细,需要一定时间理解和消化。随即搜索了一下相关的文章,于是找到了Viral Patel的这篇教程。文章图文并茂,简单易懂,短短几句话就含盖了重要的知识点,可以让人快速勾画出类文件的轮廓。做为快速入门和大概了解类文件的教程最合适不过了。又搜索了一下中文的资料,相关的文章也不少,但感觉都没有这篇适合。所以翻译一下做为参考。

 

译文:

 

我们所看到的Java字节码是被封装在一个类文件中(扩展名为.class)。在这个教程中,就让我们来看看类文件的内部构造。

数据是如何被写入类文件以及类文件的格式是怎样的呢,让我们首先图解看一看Java类文件。

 

Java类文件结构示意图:

 

上图描绘的Java类文件被分为了不同的区段,包括魔术码(magic)、版本(version)、常量池(constant pool)、访问标识(access flags)、(this)类、(super)类、接口(interfaces)、域(fields)、方法(methods)和属性(attributes)。

 

首先Java类的长度在它被加载之前是未知的,因为类中含有可变长度的区段,如常量池、方法、属性等这些区段。但这些区段的开头字节都是该区段的大小或长度信息,这样JVM在实际装载它们之前会知道这些可变长度区段的大小。写入类文件的数据是以紧凑的单字节存放的,这有助于减小类文件的大小。Java类文件中不同区段的顺序是严格规定的,以便JVM可以按其顺序载入不同区段。让我们详细看看类文件中的每个组成部分。

 

(译者注:这十个区段M agic, V ersion, C onstant pool, A ccess flags, T his, S uper, I nterfaces, F ields, M ethods, A ttributes 连起来可以用一个句英文方便记忆它们的顺序:M y V ery C ute A nimal T urns S avage I n F ull M oon A reas . 我非常可爱的小动物在滿月的地方变得疯狂。)

魔术码(magic)区段

魔术码是用来识别文件格式以便区别于其他格式。类文件的前四个字节,也就是魔术码,0xCAFEBABE。(译者注:16进制编码的写法即是英文单词CAFE BABE[咖啡宝贝],以方便记忆)


 

版本号(version)区段

 

紧跟着的四个字节包含了类文件的主要和次要版本号 。版本号数字可使JVM核实并确定类文件是否兼容。如果版本号大于JVM可以加载的版本号,类文件将无法被载入。


常量池(constant pool)区段

类或接口所定义的常量都会被储存在常量池,包括类名,变量名,接口名称,方法名称及签名,常量值,字符串文字等。常量被作为一个元素长度可变的数组存储在常量池。常量数组大小是可知的,因此,JVM在载入类文件时就知道将有多少常量在常量池。



上图中,用绿色表示的部分就是数组的大小。每一个数组元素第一个字节被用来标记这个常量的类型。上图中橙色表示的部分就是标记字节。虚拟机JVM即通过读取这个字节来识别常量的类型。假如一个字节的标记表示这是一个字符串,那么JVM就知道下面2个字节代表的是字符串长度以及之后的部分即是字符串本身。

 

(译者注:原文对常量池的描述还缺少一个关键内容:常量池计数的值是常量池中元素总数量+1,元素的下标从1开始。例如图中计数为3,那么真正紧跟着计数只有两个元素,下标为1,2。原文的配图多一个元素,在这里改正)


访问标识(access flags)区段

访问标识区段就在常量池区段之后。访问标识区段只有2个字节的数据,用来标识该文件定义的是一个类还是一个接口,是public,abstract还是final的。

This类区段

This类区段也是一个只有2个字节的数据,它的值是常量池中常量数组的一个下标。


 
上图中,This类的值0x0007指向了常量池中的一个常量。那个常量池中相应的条目由两部分组成,第一部分是一个字节的标记,代表了常量池条目的类型,是一个类或是一个接口。由上图中,橙色部分标识的常量条目的类型。后面跟着的两个字节的数据,数据的值又是常量池中的另一个常量值。图中,两个字节的值为0×0004,它指向的是常量池中的接口或类名称的字符串常量。

Super类区段

This类区段之后的2个字节就是Super类区段。结构上和This类很接近,这两个字节的值也是指向常量池里一个下标,而这个常量值后面部分指向的另一个常量值即是指向父类名的字符串。

接口(interfaces)区段

这个类或接口实现的所有接口都定义在了类文件的接口区段。接口区段最开始的2个字节提供了实现的接口的数量信息。紧接着的是一个数组,这个数组中包含着指向常量池中所实现的接口名称的字符串量常下标。

域(fields)区段

域指的是这个类的实例或接口中所定义的变量。每个类文件的域中只包含了这个类或接口内定义的变量,而不包含从父类或父接口中继承的变量。域区段中的前2个字节是一个计数,记录的是这个域中所定义的变量总数。计数之后跟着的是一个数组,数组中每个元素即是一个域变量的定义,变量定义是由长度不同的结构体组成的。有些部分变量的定义是储存在结构体中,还有些部分,如变量名是保存在常量池中的。

方法(methods)区段

方法区段中存放的是这个类或接口中所定义的所有方法,和域一样,这里不包含从父类继承的方法。区段中的头2个字节记录的也同样是这个类或接口定义的方法的数量。其余的部分同样也是一个数组,数组中的每个元素即是一个方法的结构体。每个方法结构体中包含着这个方法中的一些信息,如参数列表,返回类型,方法局部变量所需要的堆栈字数,方法运算栈所需要的堆栈字数,Exception表及字节码序列等。

属性(attributes)区段

属性区段含有这个类文件的一些属性信息,如其中一个属性是源代码属性,用来表示这个类字节码文件的源代码文件名。属性区段的头两个字节是区段中属性的个数,跟着的是属性本身。JVM会忽略掉任何它不识别的属性。

  • 大小: 9.3 KB
  • 大小: 8.2 KB
  • 大小: 8.2 KB
  • 大小: 4 KB
分享到:
评论
2 楼 cgaolei 2009-07-10  
ZangXT 写道
问题:
1.译者注:虽是16进制编码,但实际是英文单词CAFE BABE
其实这就是无符号数,并不是字符。
2.常量池(constant pool)区段
下面的图错误了吧。常量池number为3的话,常量池中只有两项,下表为1和2.
3.Super类区段
和This类很接近,这两个字节的值也是指向常量池里一个下标,指向的常量值即是指向父类名的字符串。
描述很混、存在问题。this_class部分说的很清楚,这个下表指向的是CONSTANT_Class_info类型常量,而指向字符串的部分是在这个CONSTANT_Class_info常量中。


感谢ZangXT的指正:
1. 是我的注释有误导,Magic的值是0xCAFEBABE,我的意思其实是想说这个值16进制的写法正好是英文单词Cafe Babe(咖啡宝贝),以方便记忆。

2. 的确是错的,常量池计数是常量池是项目数加1。图是原文的图,描述中也没有提到这个。我会加上注释更正,但既然是翻译,我应该尽量保留原文描述。

3. 原文中对Super类区段的解释也比较省略,因为有This类区段做参考,两个欧段结构上是相似的,只是指向的内容一个不同。

再次感请ZangXT,我会在正文中做出更正和注释。
1 楼 ZangXT 2009-07-10  
问题:
1.译者注:虽是16进制编码,但实际是英文单词CAFE BABE
其实这就是无符号数,并不是字符。
2.常量池(constant pool)区段
下面的图错误了吧。常量池number为3的话,常量池中只有两项,下表为1和2.
3.Super类区段
和This类很接近,这两个字节的值也是指向常量池里一个下标,指向的常量值即是指向父类名的字符串。
描述很混、存在问题。this_class部分说的很清楚,这个下表指向的是CONSTANT_Class_info类型常量,而指向字符串的部分是在这个CONSTANT_Class_info常量中。

相关推荐

    JAVA语言快速入门

    "JAVA语言快速入门"这个主题,旨在帮助初学者迅速掌握Java的基本概念和语法,以便快速上手编程。 首先,Java的安装与环境配置是入门的第一步。你需要下载JDK(Java Development Kit),并在计算机上设置好JAVA_HOME...

    Sun Java System Application Server快速入门指南

    ### Sun Java System Application Server 快速入门指南知识点详解 #### 一、概述 **Sun Java System Application Server** 是Sun Microsystems公司推出的一款应用服务器,用于部署和管理Java EE应用程序。本快速...

    Java基础教程(快速入门必备)pdf文件

    本教程“Java基础教程(快速入门必备)”是针对初学者精心编写的,旨在帮助他们迅速掌握Java编程的基础知识。 1. **Java语法基础**:Java语法与C++类似,但更加简洁。学习Java的第一步是了解基本的语法结构,如变量...

    Java快速入门

    Java快速入门是针对初学者的一本教程,旨在详细介绍Java编程语言的基础操作和面向对象的设计理念。Java是由Sun Microsystems公司在1995年推出的,起初是为了智能消费类家用电器的编程,随着Web的兴起,Java迅速转向...

    NetBeans+Java快速入门.pdf

    NetBeans+Java快速入门 本资源为NetBeans IDE 6.0 Java快速入门指南,旨在指导用户快速了解NetBeans IDE的工作流程和基本功能。以下是本资源的详细知识点: 一、NetBeans IDE概述 * NetBeans IDE是一个集成开发...

    SuperMap Objects Java: SWT框架 快速入门

    - **创建工程**:在你喜欢的IDE(如Eclipse)中创建一个新的Java项目,然后将SuperMap Objects Java的库文件添加到项目的类路径中。 - **设置依赖**:确保已经引入了SWT库,因为SuperMap Objects Java支持SWT来构建...

    Java-Java快速入门教程

    对于初学者来说,Java快速入门主要涉及以下几个关键知识点: 1. **环境配置**:学习Java的第一步是安装Java Development Kit (JDK)。你需要设置JAVA_HOME环境变量,并将Java编译器(javac)和Java解释器(java)添加到...

    JavaWeb 开发快速入门

    主要讲解了一个符合J2ee标准的web工程的组成结构到底是什么样,tomcat的运行机制和原理剖析,javaweb的工作原理及入门知识点

    NetBeans Java快速入门

    NetBeans Java 快速入门指南 本指南提供了使用 NetBeans IDE 创建 Java 控制台应用程序的步骤指南,涵盖了项目创建、编译和运行等基本步骤。通过这篇指南,读者将学习如何使用 NetBeans IDE 创建、编译和运行 Java ...

    java语言快速入门习题与答案

    ### Java语言快速入门知识点详解 #### 一、Java的跨平台特性 - **知识点解析**:Java语言的一个显著特点是其跨平台能力。这意味着编写的Java程序可以在任何支持Java虚拟机(JVM)的操作系统上运行而无需修改。Java的...

    java基础课件 java入门课件

    这份"java基础课件"是专为初学者设计的,旨在帮助那些对Java编程不太熟悉的人快速入门并掌握基本概念。 首先,Java的基础知识包括语法结构。在Java中,程序由类(class)组成,类是具有特定属性和行为的对象模板。...

    Java入门到精通pdf

    《Java入门到精通》是一本面向Java初学者的权威指南,旨在帮助读者快速掌握Java编程语言的基础知识并逐步深入到高级技术。这本书涵盖了从安装Java开发环境,理解基本语法,到构建复杂应用程序的全过程,是学习Java...

    优质课件 java基础入门必学 Java SE编程入门教程 全套PPT课件 共30个文件 含辅助资料.rar

    Java SE编程入门教程 javaGUI编程快速入门(1)(共82页).pptx Java SE编程入门教程 java包装器(共9页).pptx Java SE编程入门教程 java反射机制(共16页).pptx Java SE编程入门教程 java泛型(共11页).pptx Java ...

    Java编程快速入门

    Java编译器生成的是架构中立的对象文件格式,这使得编译后的代码可以在多种处理器上运行,只要有Java运行时环境(JRE)即可。Java的可移植性是因为它的架构中立性以及规范中没有任何实现依赖的方面。Java编译器用...

    NetBeans_IDE_Java快速入门教程

    通过这个快速入门教程,你可以了解到NetBeans IDE的基本使用方法,包括创建项目、编写代码、编译运行以及生成部署文件的过程。这些基础操作对于任何Java开发者来说都是至关重要的。继续探索NetBeans IDE的其他功能,...

    Java_Firebase Android快速入门示例.zip

    Java_Firebase Android快速入门示例是一个引导开发者了解如何在Android应用中集成Firebase服务的实践教程。Firebase是一个由Google提供的全面的后端平台,为开发者提供了一系列工具和服务,用于构建高质量的移动应用...

    JAVA中Hibernate快速入门程序 最简单易懂

    本教程将带你一步步了解如何在Java项目中快速入门Hibernate,以实现数据库操作的便捷化。 首先,我们需要理解Hibernate的核心概念。Hibernate通过提供一个API,将Java类与数据库表进行映射,使得开发者可以像操作...

    Java编程快速入门.docx

    当你写好一个Java程序后,你需要使用Java编译器(javac)将源代码(.java文件)编译成字节码(.class文件)。这个过程就是将人类可读的Java代码转换为JVM能理解的二进制指令。然后,通过Java解释器,JVM读取并执行...

    java基础知识入门_java_world_入门_

    本文将深入探讨Java的基础知识,帮助初学者快速入门。 首先,Java是一种面向对象的语言,它的设计理念是“一次编写,到处运行”(Write Once, Run Anywhere,简称WORA)。这意味着用Java编写的代码可以在任何支持...

Global site tag (gtag.js) - Google Analytics