`
xiaoming2xiaohong
  • 浏览: 41519 次
社区版块
存档分类
最新评论
阅读更多


Java字节码(.class文件)格式详解(一)

小介:去年在读《深入解析JVM》的时候写的,记得当时还想着用自己的代码解析字节码的,最后只完成了一部分。现在都不知道还有没有保留着,貌似Apache有现成的BCEL工程可以做这件事。当时也只是为了学习。这份资料主要参考《深入解析JVM》和《Java虚拟机规范》貌似是1.2版本的,整理出来的。里面包含了一些自己的理解和用实际代码的测试。有兴趣的童鞋可以研究研究。嘿嘿。要有错误也希望能为小弟指点出来,感激不尽。:)1.总体格式          Class File format             type         descriptor         remark             u4         magic         0xCAFEBABE             u2         minor_version                       u2         major_version                       u2         constant_pool_count                       cp_info         constant_pool[cosntant_pool_count &#8211; 1]         index 0 is invalid             u2         access_flags                       u2         this_class                       u2         super_class                       u2         interfaces_count                       u2         interfaces[interfaces_count]                       u2         fields_count                       field_info         fields[fields_count]                       u2         methods_count                       method_info         methods[methods_count]                       u2         attributes_count                       attribute_info         attributes[attributes_count]                     2.     格式详解  2.1  magic  magic被称为&#8220;魔数&#8221;,用来标识.class文件的开头。所有合法的.class字节码都应该是该数开头,占4个字节。  2.2  major_version.minor_version  major_version.minor_version合在一起形成当前.class文件的版本号,该版本号一般由编译器产生,并且由sun定义。如59.0。它们一起占4个字节。  2.3  constant_pool  在Java字节码中,有一个常量池,用来存放不同类型的常量。由于Java设计的目的之一就是字节码需要经网络传输的,因而字节码需要比较紧凑,以减少网络传输的流量和时间。常量池的存在则可以让一些相同类型的值通过索引的方式从常量池中找到,而不是在不同地方有不同拷贝,缩减了字节码的大小。  每个常量池中的项是通过cp_info的类型来表示的,它的格式如下:          cp_info format             type         descriptor         remark             u1         tag                       u1         info[]                  这里tag用来表示当前常量池不同类型的项。info中存放常量池项中存放的数据。  tag中表示的数据类型:  CONSTANT_Class_info                                  (7)、  CONSTANT_Integer_info                              (3)、  CONSTANT_Long_info                                   (5)、  CONSTANT_Float_info                                  (4)、  CONSTANT_Double_info                              (6)、  CONSTANT_String_info                                 (8)、  CONSTANT_Fieldref_info                              (9)、  CONSTANT_Methodref_info                       (10)、  CONSTANT_InterfaceMethodref_info      (11)、  CONSTANT_NameAndType_info                (12)、  CONSTANT_Utf8_info                                   (1)、  注:在Java字节码中,所有boolean、byte、char、short类型都是用int类型存放,因而在常量池中没有和它们对应的项。  2.3.1    CONSTANT_Class_info  用于记录类或接口名(used to represent a class or an interface)          CONSTANT_Class_info   format             type         descriptor         remark             u1         tag         CONSTANT_Class (7)             u2         name_index         constant_pool中的索引,CONSTANT_Utf8_info类型。表示类或接口名。        注:在Java字节码中,类和接口名不同于源码中的名字,详见附件A.     2.3.2    CONSTANT_Integer_info  用于记录int类型的常量值(represent 4-byte numeric (int) constants:)          CONSTANT_Integer_info             type         descriptor         remark             u1         tag         CONSTANT_Integer (3)             u4         bytes         整型常量值           2.3.3    CONSTANT_Long_info  用于记录long类型的常量值(represent 8-byte numeric (long) constants:)          CONSTANT_Long_info             type         descriptor         remark             u1         tag         CONSTANT_Long (5)             u4         high_bytes         长整型的高四位值             u4         low_bytes         长整型的低四位值           2.3.4    CONSTANT_Float_info  用于记录float类型的常量值(represent 4-byte numeric (float) constants:)          CONSTANT_Float_info             type         descriptor         remark             u1         tag         CONSTANT_Float(4)             u4         bytes         单精度浮点型常量值        几个特殊值:0x7f800000 => Float.POSITIVE_INFINITY、0xff800000 => Float.NEGATIVE_INFINITY、                  0x7f800001 to 0x7fffffff => Float.NaN、0xff800001 to 0xffffffff => Float.NaN     2.3.5    CONSTANT_Double_info  用于记录double类型的常量值(represent 8-byte numeric (double) constants:)          CONSTANT_Double_info             type         descriptor         remark             u1         tag         CONSTANT_Double(6)             u4         high_bytes         双精度浮点的高四位值             u4         low_bytes         双精度浮点的低四位值        几个特殊值:0x7ff0000000000000L => Double.POSITIVE_INFINITY、  0xfff0000000000000L => Double.NEGATIVE_INFINITY   0x7ff0000000000001L to 0x7fffffffffffffffL => Double.NaN 、  0xfff0000000000001L to 0xffffffffffffffffL => Double.NaN     2.3.6    CONSTANT_String_info  用于记录常量字符串的值(represent constant objects of the type String:)          CONSTANT_String_info             type         descriptor         remark             u1         tag         CONSTANT_String(8)             u2         string_index         constant_pool中的索引,CONSTANT_Utf8_info类型。表示String类型值。           2.3.7    CONSTANT_Fieldref_info  用于记录字段信息(包括类或接口中定义的字段以及代码中使用到的字段)。          CONSTANT_Fieldref_info             type         descriptor         remark             u1         tag         CONSTANT_Fieldref(9)             u2         class_index         constant_pool中的索引,CONSTANT_Class_info类型。记录定义该字段的类或接口。             u2         name_and_type_index         constant_pool中的索引,CONSTANT_NameAndType_info类型。指定类或接口中的字段名(name)和字段描述符(descriptor)。           2.3.8    CONSTANT_Methodref_info  用于记录方法信息(包括类中定义的方法以及代码中使用到的方法)。          CONSTANT_Methodref_info             type         descriptor         remark             u1         tag         CONSTANT_Methodref(10)             u2         class_index         constant_pool中的索引,CONSTANT_Class_info类型。记录定义该方法的类。             u2         name_and_type_index         constant_pool中的索引,CONSTANT_NameAndType_info类型。指定类中扽方法名(name)和方法描述符(descriptor)。           2.3.9    CONSTANT_InterfaceMethodref_info  用于记录接口中的方法信息(包括接口中定义的方法以及代码中使用到的方法)。          CONSTANT_InterfaceMethodref_info             type         descriptor         remark             u1         tag         CONSTANT_InterfaceMethodref(11)             u2         class_index         constant_pool中的索引,CONSTANT_Class_info类型。记录定义该方法的接口。             u2         name_and_type_index         constant_pool中的索引,CONSTANT_NameAndType_info类型。指定接口中的方法名(name)和方法描述符(descriptor)。           2.3.10    CONSTANT_NameAndType_info  记录方法或字段的名称(name)和描述符(descriptor)(represent a field or method, without indicating which class or interface type it belongs to:)。          CONSTANT_NameAndType_info             type         descriptor         remark             u1         tag         CONSTANT_NameAndType (12)             u2         name_index         constant_pool中的索引,CONSTANT_Utf8_info类型。指定字段或方法的名称。             u2         descriptor_index         constant_pool中的索引,CONSTANT_utf8_info类型。指定字段或方法的描述符(见附录C)           2.3.11    CONSTANT_Utf8_info  记录字符串的值(represent constant string values. String content is encoded in modified UTF-8.)  modifie   d UTF-8 refer to :   http://download.ora   cle.com/javase/1.4.2/docs/api/java/io/DataInputStream.html          CONSTANT_Utf8_info             type         descriptor         remark             u1         tag         CONSTANT_Utf8 (1)             u2         length         bytes所代表   的字符串的长度             u1         bytes[length]         字符串的byte数据,可以通过DataInputStream中的readUtf()方法(实例方法或静态方法读取该二进制的字符串的值。)           2.4  access_flags  指定类或接口的访问权限。          类或接口的访问权限             Flag Name         Value         Remarks             ACC_PUBLIC          0x0001         pubilc,包外可访问。             ACC_FINAL         0x0010         final,不能有子类。             ACC_SUPER         0x0020         用于兼容早期编译器,新编译器都设置该标记,以在使用 invokespecial指令时对子类方法做特定处理。             ACC_INTERFACE         0x0200         接口,同时需要设置:ACC_ABSTRACT。不可同时设置:ACC_FINAL、ACC_SUPER、ACC_ENUM             ACC_ABSTRACT         0x0400         抽象类,无法实例化。不可和ACC_FINAL同时设置。             ACC_SYNTHETIC          0x1000         synthetic,由编译器产生,不存在于源代码中。             ACC_ANNOTATION         0x2000         注解类型(annotation),需同时设置:ACC_INTERFACE、ACC_ABSTRACT             ACC_ENUM         0x4000         枚举类型           2.5  this_class  this_class是指向constant pool的索引值,该值必须是CONSTANT_Class_info类型,指定当前字节码定义的类或接口。     2.6  super_class  super_class是指向constant pool的索引值,该值必须是CONSTANT_Class_info类型,指定当前字节码定义的类或接口的直接父类。只有Object类才没有直接父类,此时该索引值为0。并且父类不能是final类型。接口的父类都是Object类。     2.7  interfaces  interfaces数组记录所有当前类或接口直接实现的接口。interfaces数组中的每项值都是一个指向constant pool的索引值,这些值必须是CONSTANT_Class_info类型。数组中接口的顺序和源代码中接口定义的顺序相同。     2.8  fields  fields数组记录了类或接口中的所有字段,包括实例字段和静态字段,但不包含父类或父接口中定义的字段。fields数组中每项都是field_info类型值,它描述了字段的详细信息,如名称、描述符、字段中的attribute等。          field_info             type         descriptor         remark             u2         access_flags         记录字段的访问权限。见2.8.1             u2         name_index         constant_pool中的索引,CONSTANT_Utf8_info类型。指定字段的名称。             u2         descriptor_index         constant_pool中的索引,CONSTANT_Utf8_info类型,指定字段的描述符(见附录C)。             u2         attributes_count         attributes包含的项目数。             attribute_info         attributes[attributes_count]         字段中包含的Attribute集合。见2.8.2-2.8.7        注:fields中的项目和CONSTANT_Fieldref_info中的项目部分信息是相同的,他们主要的区别是CONSTANT_Fieldref_info中的项目不仅包含了类或接口中定义的字段,还包括在字节码中使用到的字段信息。不过这里很奇怪,为什么field_info结构中不把name_index和descriptor_index合并成fieldref_index,这样的class文件不是更加紧凑吗??不知道这是sun因为某些原因故意这样设计还是这是他们的失误??     2.8.1    字段访问权限          字段的访问权限             Flag Name         Value         Remarks             ACC_PUBLIC          0x0001         pubilc,包外可访问。             ACC_PRIVATE         0x0002         private,只可在类内访问。             ACC_PROTECTED         0x0004         protected,类内和子类中可访问。             ACC_STATIC         0x0008         static,静态。             ACC_FINAL         0x0010         final,常量。             ACC_VOILATIE         0x0040         volatile,直接读写内存,不可被缓存。不可和ACC_FINAL一起使用。             ACC_TRANSIENT         0x0080         transient,在序列化中被忽略的字段。             ACC_SYNTHETIC          0x1000         synthetic,由编译器产生,不存在于源代码中。             ACC_ENUM         0x4000         enum,枚举类型字段        注:接口中的字段必须同时设置:ACC_PUBLIC、ACC_STATIC、ACC_FINAL     2.8.2    ConstantValue Attribute (JVM识别)          ConstantValue Attribute             type         descriptor         remark             u2         attribute_name_index         constant_pool中的索引,CONSTANT_Utf8_info类型。指定Attribute的名称(&#8220;ConstantValue&#8221;)。             u4         attribute_length         该Attribute内容的字节长度(固定值:2)             u2         constant_value_index         constant_pool中的索引,   CONSTANT_Integer_info(int,boolean,char、short、byte)、   CONSTANT_Float_info(float)、   Constant_Double_info(double)、   CONSTANT_Long_info(long)   CONSTANT_String_info(String)类型        每个常量字段(final,静态常量或实例常量)都包含有且仅有一个ConstantValue Attribute。ConstantValue Attribute结构用于存储一个字段的常量值。     对一个静态常量字段,该常量值会在类或接口被初始化之前,由JVM负责赋给他们,即它在任何静态字段之前被赋值。     对一个非静态常量字段,该值会被虚拟机忽略,它的赋值由生成的实例初始化函数(<init>)实现。如类:  class A {      public static final int fa = 10;      public final int fa2 = 30;      private static int sa = 20;      static {          sa = 30;      }  }  生成的字节码如下:  // Compiled from Test.java (version 1.6 : 50.0, super bit)  class org.levin.insidejvm.miscs.staticinit.A {   public static final int fa = 10;   public final int fa2 = 30;   private static int sa;    static {};       0 bipush 20       2 putstatic org.levin.insidejvm.miscs.staticinit.A.sa : int [16]       5 bipush 30       7 putstatic org.levin.insidejvm.miscs.staticinit.A.sa : int [16]      10 return   public A();       0 aload_0 [this]       1 invokespecial java.lang.Object() [21]       4 aload_0 [this]       5 bipush 30       7 putfield org.levin.insidejvm.miscs.staticinit.A.fa2 : int [23]  10 return     2.8.3    Synthetic Attribute  参考2.11.1  2.8.4    Signature Attribute  参考2.11.2  2.8.5    Deprecated Attribute  参考2.11.3  2.8.6    RuntimeVisibleAnnotations Attribute  参考2.11.4  2.8.7    RuntimeInvisibleAnnotations Attribute  参考2.11.5                                                                                                                        于2010-12-19
0
6
分享到:
评论

相关推荐

    Java字节码(.class文件)格式详解((转载)

    Java字节码是Java程序在运行时被JVM(Java虚拟机)解释执行的一种中间语言。每个Java类都由一个`.class`文件表示,其中包含了编译后的字节码指令。`.class`文件的结构非常严谨,它不仅包含了类的信息,如类名、方法...

    修改class字节码需要的工具.zip

    4. **字节码详解与字节码对应16进制网址.txt**: 这个文件可能包含了一些关于Java字节码的详细解释,以及一个链接到资源,该资源提供了字节码指令的16进制表示。理解字节码对于直接编辑字节码文件至关重要,因为字节...

    从一个class文件深入理解Java字节码结构

    【Java字节码结构解析】 Java程序在执行时,首先需要通过Java编译器将源代码(.java文件)编译成二进制的字节码文件(.class文件),这些字节码由Java虚拟机(JVM)解析并执行。深入理解字节码结构有助于我们了解...

    .class文件反编译成.java文件工具:jd-gui(无需安装,下载直接使用)

    jd-gui通过解析.class文件的字节码,将其转换回人类可读的.java源代码形式。这个过程涉及到对Java虚拟机指令的理解和源码格式的重建。尽管反编译的结果可能与原始的.java文件有所不同,尤其是在有优化或匿名内部类的...

    .class文件反编译工具

    XJad是一个早期的Java字节码反编译工具,版本2.2属于较早的版本。虽然XJad在功能上可能不如现代的反编译工具如JD-GUI、FernFlower等强大,但它在当时为开发者提供了查看和理解.class文件的途径。XJad能够将字节码...

    .class 文件反编译工具

    在Java编程领域,.class文件是Java源代码经过编译后的二进制形式,它包含了程序的字节码,是Java虚拟机(JVM)执行的基石。然而,由于.class文件是二进制格式,普通用户无法直接阅读其内容。这时,我们就需要借助于...

    Java Class文件格式详解1

    在深入讲解Class文件格式之前,我们需要理解Java字节码的概念,它是一种平台无关的中间语言,使得Java程序可以在任何支持JVM的设备上运行。 1. **总体格式** Class文件的结构遵循一个固定的模板,由多个字段组成...

    ClassFinal是一款java class文件安全加密工具

    ClassFinal的工作原理可能包括以下几点:首先,它会对输入的`.class`文件进行读取,然后通过特定的加密算法对字节码进行变换,使得原始的指令序列变得难以理解。加密后的字节码在Java虚拟机(JVM)加载时,需要经过...

    字节码文件结构详解.docx

    Class 文件是 Java 字节码的核心载体,它是一种二进制流,以 8 位字节为基础单位,数据项紧凑排列,不包含额外的分隔符。遇到需要超过 8 字节存储的数据时,采用 Big-Endian 字节顺序存储,以确保跨平台兼容性。Big-...

    【JVM和性能优化】3.JVM的执行子系统

    文章目录Class 文件格式字节码Class类的本质Class文件格式类加载机制加载验证准备解析初始化类加载器双亲委派机制栈桢JVM方法调用详解方法解析静态分派动态分派参考 Class 文件格式 一般情况下Java代码执行流程如下...

    Java新手入门.md

    此命令会根据`HelloWorld.java`生成`HelloWorld.class`文件,即字节码文件。字节码是一种中间代码,由Java虚拟机(JVM)解释执行。 **1.4 运行Java程序** 编译成功后,使用`java`命令来运行程序: ```bash java ...

    java与javac命令详解

    * -d &lt;目录&gt;:指定 Java 源文件编译之后生成的字节码 .class 文件的存放位置。 source 指 Java 源文件名,包括文件扩展名 .java。 java 命令的语法为:java [option] classname [arguments] 其中,option 是可...

    java虚拟机详解.docx

    3. **Java虚拟机(JVM)**:这是一个模拟计算机环境,能够解释执行Java字节码文件,并处理内存管理、垃圾回收等任务,确保程序的安全性和可移植性。 4. **Java应用程序接口(API)**:提供了一系列预定义的类和接口,...

    jclazz win JAVA 字节码查看器

    《jclazz:Windows平台上的JAVA字节码查看器详解》 在Java开发过程中,了解和分析字节码是提升程序理解和优化能力的重要手段。jclazz是一款专为Windows平台设计的JAVA字节码查看器,其1.1.2版本以其易用性和功能...

    JAVA文件中调用已编译的.CLASS的类.doc

    在Java开发中,源文件(`.java`)首先需要通过`javac`命令进行编译,生成字节码文件(`.class`)。这一步骤是Java程序执行的基础。编译的过程涉及到语法检查、类型检查等步骤,确保代码符合Java语言规范。 2. **...

    Java lambda表达式和JVM字节码功能详解.pdf

    在Java字节码中,我们可以看到Lambda表达式是如何被转化为一个内部类`InnerClass$1`的,这个内部类实现了`Function`接口并重写了`apply`方法。字节码指令如`new`, `dup`, `invokespecial`和`putfield`等用于创建并...

    JAVA Class文件结构

    在Java编程语言中,`.class`文件是一种重要的二进制文件格式,用于存储Java类的编译结果。这些文件由Java编译器生成,并作为Java虚拟机(JVM)执行的基础。本文将深入探讨`.class`文件的结构,帮助读者理解其组成部分...

Global site tag (gtag.js) - Google Analytics