`
爪哇岛岛主
  • 浏览: 38765 次
  • 性别: Icon_minigender_1
  • 来自: 杭州(也就是天堂)
社区版块
存档分类
最新评论

浅析class文件内部结构

阅读更多
      最近在为工作的事情搞的很是纠结。由于前段时间在iteye上发表了一篇“应届生,求内推”的帖子,也联系了几个“内推手”。虽然后来不成功,不过还是要感谢大部分人。究其原因可能是因为我人在南昌,看到简历后觉得离工作的地方太远,所以没有发面试通知把。不过找工作是找工作,学习还是不能忘记的。下面的这篇文章,是我这几天看《深入浅出java 虚拟机》第六章 总结出来的一些自己的东西。
      我在这里主要讲的是class file 文件结构。首先要给出两张表,第一张是class文件基本类型,第二张是class文件格式。
表6-1 class文件“基本类型”
u1 1个字节,无符号类型
u2 2个字节,无符号类型
u4 4个字节,无符号类型
u8 8个字节,无符号类型


表6-2 classfile表的格式
类型 名称 数量
U4 Magic 1
U2 Minor_version 1
U2 Major_version 1
U2 Constant_pool_count 1
Cp_info Constant_pool Constant_pool_count-1
U2 Access_flags 1
U2 This_class 1
U2 Super_class 1
U2 Interfaces_count 1
U2 Interfaces Interfaces_count
U2 Fields_count 1
Field_info Fields Fields_count
U2 Methods_count 1
Method_info Methods Methods_count
U2 Attributes_count 1
Attribute_info Attributes Attributes_count
对于这个表的格式,我不想全部翻译其意义,就前面几个字段的意义做一下简要说明就行了,后面的都可以“观其字面意思,就可知其内部含义”。
(1)magic(魔数)
每一个java class文件的前4个字节被称为它的魔数(magic number):0XCAFEBABE。魔数的作用在于,可以轻松地分辨出java class文件和非java class文件。如果一个文件不是以0xCAFEBABE开头。那它就肯定不是java class文件。文件格式定义者能够自由选择魔数,前提是这个选定的魔数值没有被广泛应用。当java还被称为“Oak”的时候,这个魔数就已经定下来了。一招Patrick Naughton(最初java开发小组的关键成员)的说法:“早在java第一次作为该语言的名字发布以前,我们就在寻找一些好玩的、唯一的、容易记忆的东西。选择0xCAFEBABE只不过是一个巧合,它象征着著名咖啡品牌Peet’s Coffee中深受欢迎的baristas(一种咖啡名称)。它预示了java这个名字的出现”。
(2)minor_version和major_version
Class文件的下面4个字节包含了主、次版本号。随着java技术的发展,java class文件格式可能会加入新特性。Class文件格式一旦发生变化,版本号也会随之变化。对于java虚拟机来说,版本号确定了特定的class文件格式,通常只有给定主版本号和一系列次版本号后,java虚拟机才能够读取class文件。如果class文件的版本号超出了java虚拟机所能处理的有效范围,java虚拟机将不会处理该class文件。
在sun的jdk1.0.2发布版中,java虚拟机实现支持从45.0(主版本号为45,次版本号为0)到45.3的class文件格式。在所有jdk1.1发布版中的虚拟机都能够支持版本从45.0到45.65535的class文件格式。在sun的1.2版本的sdk中,虚拟机能够支持从版本45.0到46.0的class文件格式。
1.0或1.2版本的编译器能够产生版本号为45.3的class文件。在sun的1.2版本sdk中,javac编译器默认产生版本号为45.3的class文件。但如果在javac命令行中指定了-target1.2标志,1.2版本的编译器将产生版本号为46.0的class文件。1.0或1.1版本的虚拟机上不能运行使用-target1.2标志所产生的class文件。
Java虚拟机实现的第二版中修改了对class文件主版本号和次版本号的解释。对于第二版而言,class文件的主版本号与java平台主发布版的版本号保持一致(例如:在java2平台发布版上,主版本号从45到46),次版本号与特定主平台发布版的各个发布版相关。因此,尽管不同的class文件格式可以由不同的版本号表示,但版本号不一样并不代表class文件格式不同。版本号不同的原因可能只是因为class文件由不同发布版本的java平台产生,可能class文件的格式并没有改变。
(3)constant_pool_count和constant_pool
在class文件中,魔数和版本号后面的是常量池。正如第五章中所述,常量池包含了与文件中类和接口相关的常量。常量池中存储了注入文字字符串、final变量值、类名和方法名的常量。Java虚拟机把常量池组织为入口列表的形式。在实际列表constant_pool之前,是入口在列表中的计数constant_pool_count。
(4)access_flags
紧接常量池后的两个字节称为access_flags,它展示了文件中定义的类或接口的几段信息。例如,访问标志指明文件中定义的是类还是接口;访问标志还定义了在类或接口的声明中,使用了哪种修饰符;类和接口是抽象的,还是公共的;类的类型可以为final,而final类不可能是抽象的;接口不能为final类型。

下面我根据一个实例来简要剖析class文件结构
首先,新建一个java源文件,并且编译出class文件。这个事用来做实验的,随便一点就OK了。

类名称:MyTest.java
package app;

/**
 * <p>
 *  这是一个测试源文件,用来生成class文件,分析class文件结构
 * </p>
 * @author 杨
 *
 */
public class MyTest {

	/**
	 * 属性列表
	 */
	private Integer id;
	private String name;
	
	/**
	 * 构造器
	 */
	public MyTest(){
		this.id = 0;
		this.name = "";
	};
	
	/**
	 * 重载构造函数
	 */
	public MyTest(Integer id,String name){
		this.id = id;
		this.name = name;
	}

	/**
	 *属性存取方法
	 */
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
}


编译后的MyTest.class文件内容如下(以文本方式打开):
漱壕   1 )  
app/MyTest  java/lang/Object id Ljava/lang/Integer; name Ljava/lang/String; <init> ()V Code
  
 	 

    java/lang/Integer   valueOf (I)Ljava/lang/Integer;	       	     LineNumberTable LocalVariableTable this Lapp/MyTest; ((Ljava/lang/Integer;Ljava/lang/String;)V getId ()Ljava/lang/Integer; setId (Ljava/lang/Integer;)V getName ()Ljava/lang/String; setName (Ljava/lang/String;)V 
SourceFile MyTest.java !                  	 
     I     * *  *                                	      Y     * *+ *,               	                                      /     *            &              ! "     >     *+        
    *  +                    # $     /     *            .              % &     >     *+        
    2  3                    '    (


其实从上面的class文件中也可以看出一点端倪出来(尽管是乱码居多)。

我们现在分析一下class文件结构对应于上面给出那张表,每个项在这个文件中所指示的具体的值。当然了,这种乱码打开的肯定不适合分析,那就以16进制方式打开把。

CA FE BA BE 00 00 00 31  00 29 07 00 02 01 00 0A
61 70 70 2F 4D 79 54 65  73 74 07 00 04 01 00 10
6A 61 76 61 2F 6C 61 6E  67 2F 4F 62 6A 65 63 74
01 00 02 69 64 01 00 13  4C 6A 61 76 61 2F 6C 61
6E 67 2F 49 6E 74 65 67  65 72 3B 01 00 04 6E 61
6D 65 01 00 12 4C 6A 61  76 61 2F 6C 61 6E 67 2F
53 74 72 69 6E 67 3B 01  00 06 3C 69 6E 69 74 3E
01 00 03 28 29 56 01 00  04 43 6F 64 65 0A 00 03
00 0D 0C 00 09 00 0A 0A  00 0F 00 11 07 00 10 01
00 11 6A 61 76 61 2F 6C  61 6E 67 2F 49 6E 74 65
67 65 72 0C 00 12 00 13  01 00 07 76 61 6C 75 65
4F 66 01 00 16 28 49 29  4C 6A 61 76 61 2F 6C 61
6E 67 2F 49 6E 74 65 67  65 72 3B 09 00 01 00 15
0C 00 05 00 06 08 00 17  01 00 00 09 00 01 00 19
0C 00 07 00 08 01 00 0F  4C 69 6E 65 4E 75 6D 62
65 72 54 61 62 6C 65 01  00 12 4C 6F 63 61 6C 56
61 72 69 61 62 6C 65 54  61 62 6C 65 01 00 04 74
68 69 73 01 00 0C 4C 61  70 70 2F 4D 79 54 65 73
74 3B 01 00 28 28 4C 6A  61 76 61 2F 6C 61 6E 67
2F 49 6E 74 65 67 65 72  3B 4C 6A 61 76 61 2F 6C
61 6E 67 2F 53 74 72 69  6E 67 3B 29 56 01 00 05
67 65 74 49 64 01 00 15  28 29 4C 6A 61 76 61 2F
6C 61 6E 67 2F 49 6E 74  65 67 65 72 3B 01 00 05
73 65 74 49 64 01 00 16  28 4C 6A 61 76 61 2F 6C
61 6E 67 2F 49 6E 74 65  67 65 72 3B 29 56 01 00
07 67 65 74 4E 61 6D 65  01 00 14 28 29 4C 6A 61
76 61 2F 6C 61 6E 67 2F  53 74 72 69 6E 67 3B 01
00 07 73 65 74 4E 61 6D  65 01 00 15 28 4C 6A 61
76 61 2F 6C 61 6E 67 2F  53 74 72 69 6E 67 3B 29
56 01 00 0A 53 6F 75 72  63 65 46 69 6C 65 01 00
0B 4D 79 54 65 73 74 2E  6A 61 76 61 00 21 00 01



分析:
项目 所占位数 说明
Magic(魔数) 4 CA FE BA BE 符合class文件格式
Minor_version(次版本号) 2 00 00 0
Major_version(主版本号) 2 00 31  十进制是49(JDK1.6)
Constant_pool_count(常量池数) 2 00 29 41个
Constant_pool 不定(cp_info) 后面一大串


心情不好,休息。下个礼拜可能去上海找工作。
分享到:
评论

相关推荐

    浅析Java卡应用执行机制及虚拟机能效优化.pdf

    Java卡应用执行机制主要是将class文件的字节码转换成可以被Java虚拟机识别并执行的虚拟机代码。由于Oracle公司在JCVMSpecification中明确规定了Java虚拟机所支持的所有指令集,因此这是一个标准的转换过程。 二、B...

    Java类加载原理浅析

    Java类加载原理是Java虚拟机(JVM)的重要组成部分,它负责将类的.class文件从磁盘或网络中加载到内存,并转化为运行时的数据结构,以便执行程序代码。本文将深入探讨类加载机制,包括加载、连接、初始化三个主要...

    浅析使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")

    `Class.forName()`方法在Java官方文档中被描述为在运行时动态加载一个类并返回`Class`对象。在JDBC中,`Class.forName("com.mysql.jdbc.Driver")`的作用是加载MySQL的JDBC驱动类,即`com.mysql.jdbc.Driver`。虽然...

    MFC异常处理浅析[定义].pdf

    THROW宏用于重新抛出当前的异常,这在需要在异常处理程序内部进行一些操作后再次抛出异常时非常有用。THROW_LAST宏则是抛出最近一次捕获的异常,并清理相关的资源。 MFC还定义了一个CException类,它是所有预定义...

    浅析TypeScript 命名空间

    如上述示例所示,`namespace` 关键字用于创建命名空间,内部可以定义接口、类等类型。若想让这些类型在外部可访问,需使用 `export` 关键字导出。例如,`Drawing` 命名空间包含了`IShape`接口和`Circle`、`Triangle`...

    浅析Spring Boot中的spring-boot-load模块

    通常,Java的类加载器只能加载JAR内部当前目录下的类文件,但`spring-boot-loader`允许我们使用`java -jar`命令运行包含嵌套依赖JAR的单一可执行JAR或WAR文件。它提供了三种类启动器:`JarLauncher`、`WarLauncher`...

    浅析Python面向对象编程

    面向对象编程(Object-Oriented Programming,简称OOP)是一种重要的编程范式,它通过类(Class)和对象(Object)来组织代码,强调代码的结构化和重用性。Python语言支持丰富的面向对象特性,使得它在各种应用场景...

    浅析BootStrap中Modal(模态框)使用心得

    模态框由`.modal`类定义,内部包含`.modal-dialog`、`.modal-content`、`.modal-header`、`.modal-body`和`.modal-footer`等部分。以下是一个简单的示例: ```html &lt;!-- 按钮触发模态框 --&gt; &lt;button class="btn btn...

    PHP中的命名空间相关概念浅析

    在命名空间的内部,相同的类名、函数名或者常量名可以共存而不产生冲突,因为它们处于不同的命名空间内。此外,命名空间之间可以互相引用,但在引用其他命名空间的元素时必须使用完全限定名,也就是包含命名空间路径...

    浅析AngularJS中的指令

    编译函数用于编译模板,生成指令的DOM结构,而控制器函数用于处理指令内部的逻辑。 指令系统的设计目标是让开发者能够利用AngularJS强大的数据绑定和依赖注入等特性,快速创建可复用的组件,并将它们组织成一个清晰...

    ES6中module模块化开发实例浅析

    一个ES6模块本质上是一个独立的JS文件,每个文件都拥有自己的作用域,这意味着在模块内部定义的变量不会污染全局命名空间。有两点值得注意: 1. **自动开启严格模式**:ES6模块会自动运行在严格模式下,这是为了...

    《Hadoop开发者》第三期

    这使得用户能够在MapReduce作业中处理结构化数据,而这些数据通常存储在关系型数据库中,如MySQL、PostgreSQL和Oracle等。 #### 内置类详解 DBInputFormat内部定义了三个关键类来实现其功能: 1. **...

    jquery开发入门整理(所需要了解的)

    - **DOM (Document Object Model)**:描述了如何以结构化的方式表示文档,以及如何通过JavaScript操作文档中的元素。 ### 深入解读JavaScript中BOM和DOM - **BOM**:主要关注浏览器环境,如窗口大小、弹窗操作等。 ...

    SAP屠夫作品汇总

    [4]定义状态主文件(Tcode:OK02|BS02) 326 [5]定义受权码(Tcode:BS52/BS53) 328 [6](Tcode:KOV2) 328 [7]分配状态管理给订单类型(Tcode: 328 例1.设置订单审批流程 328 例2.使用投资订单管理固定资产项目 332 CO-CCA ...

    ARCGIS 开发集锦 地理信息系统的二次开发

    4. **创建图层:** 通过`IFeatureWorkspace`接口从工作空间中获取特征工作空间(`FeatureWorkspace`),进而创建特征类(`FeatureClass`),即新的图层。 5. **加载图层:** 将创建好的特征类添加到地图控件(`...

Global site tag (gtag.js) - Google Analytics