Java诞生之始就提出一个口号叫“Write once,Run anywhere”,即代码编写一次、编译一次之后就可在所有平台上通用。实现平台无关性的基石是各种平台不同的虚拟机和所有平台统一使用的程序存储格式——字节码。这里的虚拟机相当于手机充电的转换头。这些字节码是存储在class文件中的,了解class文件结构是了解jvm的基础。
class文件是不包含任何的分隔符的,因此想要虚拟机读懂它就必须严格规定文件中数据项的顺序数量以及数据存储的字节序(class文件的字节序为Big-Endian),总体结构如下表。class文件的数据类型就两种:无符号数和表。无符号数用于描述数字、索引引用、数量值、或者是utf-8编码的字符串值,我们用u1、u2、u4、u8代表相应数量的无符号数。表就是有一定结构的无符号数,表名称习惯以“_info”结尾,其实整个class文件就能看做是一张表。当需要描述同一类型的不定数量的多个数据时,经常使用一个前置容量计数器加若干个连续数据项,我们称之为某一类型的集合。比如下表中的constant_pool常量池前的constant_pool_count。
下面我们结合一个类分析它的class文件结构,java文件和class文件内容如下。class文件用两种颜色区分每个部分
package com.cq.test; public class TestClass{ private int m; public int inc(){ return m+1; } }
①:magic魔数,唯一作用就是辨别是否class文件。作用真不大...class文件的魔数是0xCAFEBABE(咖啡?宝贝)
②:文件版本,第5、6字节是次版本号这里是0000,7、8字节是主版本号。jdk1.1的主版本号为45,之后大版本发布一次往上加1,0x0034即52说明笔者使用的是jdk1.8
③:常量池集合,0x0013(19)是常量池容量计数器。即有18个常量,从1开始计数,索引值范围为1~18,还有一个索引值为0的用于在特定情况下表达“不引用任何一个常量池项目”,合起来19个。
常量池中每一项都是一个表,都有各自的结构,长度也不尽相同,因此必须有个标志来区别属于那种表。上面紧接0x0013的是0x0A表示第一个常量是CONSTANT_Methodref_info表,其表结构是:tag u1、class_index u2(指向类或接口描述符的索引项)、name_and_type_index u2(指向名称及类型描述符的索引项)。所以第一项常量的内容为0x0A0004000F,表示该方法所属类的是第4个常量所表示的类,第15个常量表示了方法的简单名称和描述符(包括参数和返回类型等)
④:访问标志,这16位的二进制数用于描述类的访问信息,包括这个是否是接口;是否定义为public;是非是abstract等等。16位中一共使用了8位来描述1则为是0则为否。0x0021中0x0001表示为public类型的类,0x0020是jdk1.0.2之后都必须为真的值。
⑤:类索引、父类索引、接口索引集合,0x0003表示第3个常量描述了这个类,父类同。由于这个类没有继承接口则interface_count为0x0000
⑥:字段表集合,字段表的结构:access_flag u2;name_index u2;descriptor_index u2;attributes_count u2;arrtibutes 属性表具体长度看表结构 (字段值应该是在实例生成时由构造方法赋值的)
集合长度:0x0001 表示该类就一个字段
access_flag:类似访问标志0x0002表示字段是private的
name_index:索引值指向常量池,代表字段名称,这里指向第5项常量值为“m”
descriptor_index:索引值指向常量池,代表字段的类型,第6项常量值为“I”,表示这个字段是int类型的值。其他的F表示float类型,Z表示boolean类型,对象类型则用L加对象全限定名表示如:Ljava/lang/Object,数组的话则前置一个“[”来表示,如一个String[]数组,将被记录为“[Ljava/lang/String”
attributes_count:属性数量,这个例子中字段没有属性
attribute:属性
⑦:方法表集合,方法表结构与字段表结构一样。当然access_flag位所表示的含义与字段是不一样的。另外所有包含方法体的方法都有一个属性Code,方法体的字节码就存放在Code中
⑧:其他属性,最后一部分的0x0001表示还有一个其他属性0x000D是索引值表示属性名称,查询得第13个常量是值为“SourceFile”的utf8表。“SourceFile”属性的表结构为:attribute_name_index u2;attribute_length u4;sourcefile_index u2。
当然这样直接看字节码是不直观的,还可以通过jdk的javap工具的-verbose参数输出class文件字节码内容,现将该示例的字节码内容粘贴如下
Classfile /D:/TestClass.class Last modified 2016-10-8; size 287 bytes MD5 checksum 89c5dc104dfcc5ee3da3c336334615d9 Compiled from "TestClass.java" public class com.cq.test.TestClass minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #4.#15 // java/lang/Object."<init>":()V #2 = Fieldref #3.#16 // com/cq/test/TestClass.m:I #3 = Class #17 // com/cq/test/TestClass #4 = Class #18 // java/lang/Object #5 = Utf8 m #6 = Utf8 I #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 LineNumberTable #11 = Utf8 inc #12 = Utf8 ()I #13 = Utf8 SourceFile #14 = Utf8 TestClass.java #15 = NameAndType #7:#8 // "<init>":()V #16 = NameAndType #5:#6 // m:I #17 = Utf8 com/cq/test/TestClass #18 = Utf8 java/lang/Object { public com.cq.test.TestClass(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 public int inc(); descriptor: ()I flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: getfield #2 // Field m:I 4: iconst_1 5: iadd 6: ireturn LineNumberTable: line 7: 0 } SourceFile: "TestClass.java"
相关推荐
### Class文件结构浅析 #### 一、引言 在深入了解Class文件的结构之前,我们需要明确Class文件在Java生态系统中的重要地位。Java程序被编译器编译后生成的`.class`文件,实际上是字节码文件,它们是Java虚拟机...
### Class文件结构详解 #### 一、概述 `class`文件是Java编译器生成的目标文件格式,也是Java虚拟机执行的基本单位。每个`.class`文件代表了一个Java类或者接口的定义,包含了类的元数据(如常量池、访问标志、类...
### Class文件结构组成详解 #### 一、Class文件概述 Class文件是Java程序编译后的产物,由编译器生成并被Java虚拟机(JVM)加载执行。它以8位字节流的形式组织数据,共包含15个有意义的组成部分。每个部分紧密相连,...
第一章:class文件结构.mmap
Java虚拟机中的class类文件的知识,个人整理大的class类文件结构.xmind,有什么问题及时反馈。
#### 二、Class文件的基本结构 ##### 1. 魔数与版本号 - **魔数**:每个`.class`文件的开头四个字节称为“魔数”,其值固定为`CAFEBABE`。这是为了确认该文件是否为有效的`.class`文件,以及防止由于文件损坏等原因...
class文件的结构设计使得它可以跨平台运行在任何安装有Java虚拟机的机器上。class文件包含了Java源代码编译成的字节码指令、符号引用以及其他信息,是Java平台无关性的关键。 首先,class文件是由8位字节组成的二...
Class文件结构1
Class文件的结构是理解JVM工作原理的关键。本文将深入探讨Class文件的主要组成部分,包括魔数、版本号、常量池、访问标志、类索引、父类索引、接口、字段、方法以及属性。 1. **魔数**:每个Class文件的开头都有一...
jdk1.7_class文件结构分析,常量池分析;jdk1.7_class文件结构分析,常量池分析;
JavaClassViewer-2.0.4, 用于理解Class文件结构。 解析出class结构,以及十六进制的表示,特别方便。 原下载地址: http://www.softpedia.com/get/Programming/File-Editors/Java-Class-Viewer.shtml。另外也可以参考...
class文件结构参照表全集
Class文件结构明细,各种详细的指标,以java1.8版本为例。
class文件结构解析字节码后文件
class文件结构第一章学习
### JavaClass文件的结构分析及其校验 #### 引言 随着Java技术的不断发展与广泛应用,JavaClass文件作为Java程序的基础组成部分,其结构与验证机制的重要性日益凸显。本文旨在深入探讨JavaClass文件的结构特点,并...
Java Class文件是Java源代码经过编译器处理后的二进制形式,它们包含了程序的结构信息,如类、接口、变量、方法等定义。在Java开发过程中,有时我们需要查看或分析这些Class文件,以理解程序运行原理、调试或逆向...
Class文件结构是JVM的核心组件之一,对于Java开发者来说,理解Class文件结构是非常重要的。本文将深入解释Class文件结构的详细信息,包括Class文件的组成部分、常量池、访问标志、类索引、字段表集合、方法表集合、...
本压缩包文件提供了两个示例项目,分别展示了JDK动态代理和CGLib动态代理的实现,帮助我们理解这两种技术的工作原理以及它们生成的class文件结构。 首先,我们来详细了解JDK动态代理。JDK动态代理基于Java的接口...
以思维导图的方式概括了java class文件的结构。其中用位置描述了各个结构出现的顺序。为JVM的一个分支。