class文件格式_如何查看class文件编码格式 - CSDN
精华内容
参与话题
  • 1.class文件格式 2.常量池中各类信息 3 访问修饰符 4.fields 5.Method 6.Attributes 7.The code attribute 8.Exceptionattribute 9.LineNumberTable_attribute 1.class文件格式 ClassFile { u4 magic; ...

     

    目录

             1.class文件格式

    2.常量池中各类信息

    3 访问修饰符

    4.fields

    5.Method

    6.Attributes

    7.The code attribute

    8.Exception attribute

    9.LineNumberTable_attribute


     1.class文件格式

    ClassFile {
        u4             magic;
        u2             minor_version;
        u2             major_version;
        u2             constant_pool_count;
        cp_info        constant_pool[constant_pool_count-1];
        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.常量池中各类信息

    JAVA常量池
    常量 项目 类型 描述
    CONSTANT_utf8_info tag U1 值为1
    length U2 UTF-8编码的字符串长度
    bytes U1 长度为length的UTF-8编码的字符串
    CONSTANT_Integer_info tag U1 值为3
    bytes U4 按照高位在前存储的int值
    CONSTANT_Float_info tag u1 值为4
    bytes u4 按照高位在前存储的float值
    CONSTANT_Long_info tag u1 值为5
    bytes U8 按照高位在前存储的long值
    CONSTANT_Double_info tag u1 值为6
    bytes u8 按照高位在前存储的Double值
    CONSTANT_Class_info tag u1 值为7
    index u2 指向全限定名常量项的索引
    CONSTANT_String_info tag u1 值为8
    index u2 指向字符串字面量的索引
    CONSTANT_Fieldref_info tag u1 值为9
    index u2 指向声明字段的类或者接口描述符CONSTANT_Class_info的索引项
    index u2 指向字段描述符CONSTANT_NameAndType_info的索引项
    CONSTANT_Methodref_info tag u1 值为10
    index u2 指向声明方法的类的描述符CONSTANT_Class_info的索引项
    index u2 指向方法描述符CONSTANT_NameAndType_info的索引项
    CONSTANT_InterfaceMethodref_info tag u1 值为11
    index u2 指向声明方法的类的描述符CONSTANT_Class_info的索引项
    index u2 指向方法描述符CONSTANT_NameAndType_info的索引项
    CONSTANT_NameAndType_info tag u1 值为12
    index u2 指向该字段或者方法名称常量项的索引
    index u2 指向该字段或者方法描述符常量项的索引
    在终端运行 javap com.mi.jbytecode.MyTest1
    1.使用javap -verbose 命令分析一个字节码时,将会分析该字节码文件的魔数,版本号,常量池,类信息,类的构造方法,类中的方法信息,类变量与成员变量等信息
    2.魔数:所有.class字节码文件的前4个字节都是魔数,魔数值为固定值:0xCAFEBABE.
    3.魔数之后的4个字节是版本信息,前两个字节是 minor version(次版本号),后两个字节是major version(主版本号)。这里的版本号 00 00 00 34,
    换算成10进制,表示次版本号为0,主版本号为52,所以该文件的版本号为:1.8.0.可以通过java -version命令来验证这一点
    4.常量池:紧接着主版本号之后的就是常量池入口,一个java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是Class文件的资源仓库
    ,比如说JAVA类中定义的方法和变量信息,都是存储在常量池中的,常量池中主要存储的两类常量:字面量与符号引用。字面量如文本字符串,
    java中声明为final的常量值,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符等。
    5.常量池的总体结构:java类所对应的常量池主要由常量池数量和常量池数组两部分共同构成,常量池数量紧跟在主版本号后面,占据2个字节;常量池数组紧跟在常量池数量之后,
    常量池数组和一般的数组不同的是,常量池数组中不同的元素的类型,结构都是不同的,长度当然也就不同;但是,每一钟元素的第一个数据都是一个U1类型,
    该字节是个标志位,占一个字节,JVM在解析常量池时,会根据这个U1类型来获取元素的具体类型。值得注意的是,常量池数组钟元素的个数 = 常量池数 - 1 (其中0暂时不使用)
    ,目的是满足某些常量池索引值的数据在特定情况下需要达到 【不引用任何一个常量池】的含义,根本原因在于,索引为0也是一个常量(保留常量),只不过
    它不位于常量表中,这个常量就对应null值;所以,常量池的索引从1开始而非0开始。
    6.在JVM规范中,每个变量/字段都有描述信息,描述信息主要的作用是描述字段的数据类型,方法的参数列表(包括数量,类型,顺序)与返回值。
    根据描述符规则,基本数据类型和代表无返回值的void类型都用一个大写字母来表示,为了压缩字节码文件的体积,对于基本数据类型,JVM都只使用一个大写字母来表示,如下所示:
    B - byte , C -char ,D - double ,F - float , I - int ,J - Long , S -short , z - boolean, V -void, L -对象类型,如Ljava/lang/String;
    7.对于数组类型来说,每一个维度使用一个前置【来表示, 如int[]被记录为[I,String[][] 被记录为[[Ljava/lang/String;
    8.用描述符描述方法的时候先按照参数列表,后返回值的顺序来描述,参数列表按照参数的严格顺序放在一组()之内,
    如方法:String getRealnamebyIdAndNickname(int id , String name)的描述符为:(I,Ljava/lang/String)Ljava/lang/String.
     */

    3 访问修饰符

    ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its package.
    ACC_PRIVATE 0x0002 Declared private; usable only within the defining class.
    ACC_PROTECTED 0x0004 Declared protected; may be accessed within subclasses.
    ACC_STATIC 0x0008 Declared static.
    ACC_FINAL 0x0010 Declared final; never directly assigned to after object construction (JLS §17.5).
    ACC_VOLATILE 0x0040 Declared volatile; cannot be cached.
    ACC_TRANSIENT 0x0080 Declared transient; not written or read by a persistent object manager.
    ACC_SYNTHETIC 0x1000 Declared synthetic; not present in the source code.
    ACC_ENUM 0x4000 Declared as an element of an enum.
    ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the invokespecial instruction.

     访问修饰符在字节码中是并集存在的,例如一个类的访问修饰符00 21就是0001和0020的并集。

    4.fields

    field_info {
        u2             access_flags;
        u2             name_index;
        u2             descriptor_index;
        u2             attributes_count;
        attribute_info attributes[attributes_count];
    }

    5.Method

    method_info {
        u2             access_flags;
        u2             name_index;
        u2             descriptor_index;
        u2             attributes_count;
        attribute_info attributes[attributes_count];
    }

     对于java的每一个实例方法(非static方法)其在编译后所生成的字节码当中,方法参数的数量总是会比源代码中方法参数的数量多一个(this),它位于方法参数的第一个位置,这样我们就可以在java实例方法中使用this去访问当前对象的属性及其他方法,这个操作是在编译期间完成的,即,由javac编译器在编译的时候将这个this的访问转化为一个普通实例参数的访问;接下来在运行期间,由jvm在调用实例方法时自动向实例方法中传入this参数,所以实例方法的局部变量表中至少会有一个指向当前对象的局部变量

    6.Attributes

    attribute_info {
        u2 attribute_name_index;
        u4 attribute_length;
        u1 info[attribute_length];
    }

    7.The code attribute

    Code_attribute {
        u2 attribute_name_index;
        u4 attribute_length;
        u2 max_stack;
        u2 max_locals;
        u4 code_length;
        u1 code[code_length];
        u2 exception_table_length;
        {   u2 start_pc;
            u2 end_pc;
            u2 handler_pc;
            u2 catch_type;
        } exception_table[exception_table_length];
        u2 attributes_count;
        attribute_info attributes[attributes_count];
    }

    8.Exception attribute

    Exceptions_attribute {
        u2 attribute_name_index;
        u4 attribute_length;
        u2 number_of_exceptions;
        u2 exception_index_table[number_of_exceptions];
    }

    9.LineNumberTable_attribute

    LineNumberTable_attribute {
        u2 attribute_name_index;
        u4 attribute_length;
        u2 line_number_table_length;
        {   u2 start_pc;
            u2 line_number;	
        } line_number_table[line_number_table_length];
    }

    等等信息,我们就可以手动的一个字节一个字节的去反编译一个类如下

    package cn.sh.bytecode;
    
    public class Demo1 {
        private int a = 1;
    
        public Demo1() {
        }
    
        public int getA() {
            return this.a;
        }
    
        public void setA(int a) {
            this.a = a;
        }
    }
    

    值得注意的地方

    1.在字节码中当这个类没事实现接口时,存在接口总数,不存在接口详细信息,方法没有异常时,存在异常总数,但不存在异常信息,

    2.类,字段,方法的访问权限是以并集的方式将多个权限并在2个字节中;

    3.处理异常时在方法名处声明异常和用try-cath 捕获异常它们在方法中的地位是不一样的,前者与code处于同级别,而后者则是在code 执行字节码中是以goto的形式存在的,有多少个catch就有多少个goto;

    4.在用try-catch捕获异常时若有finally块,底层字节码是将finally块拼接到每一个goto之后;

    5.jvm处理异常时会有一个exception table,这张表详细描述了处理异常的信息,每一个exception table表项由start_PC,end_PC,handler_PC,catch_type组成。

    展开全文
  • CLASS文件结构

    2020-03-23 10:36:18
    class文件各部分内容代表内容 观察ByteCode方法 JDK自带工具 javap javap命令,显示class信息,详细如下: C:\>javap D:\idea_gitlab_workspace\test111\out\production\test111\com\xi...

    查看16进制格式的ClassFile

    • sublime / notepad
    • IDEA插件 - binEd

    class文件内容

    • 新建一个类
    public class Test {
    }
    
    • 编译改类,生成class文件,使用sublime打开
    cafe babe 0000 0034 0010 0a00 0300 0d07
    000e 0700 0f01 0006 3c69 6e69 743e 0100
    0328 2956 0100 0443 6f64 6501 000f 4c69
    6e65 4e75 6d62 6572 5461 626c 6501 0012
    4c6f 6361 6c56 6172 6961 626c 6554 6162
    6c65 0100 0474 6869 7301 0019 4c63 6f6d
    2f78 6961 6368 772f 6a76 6d74 6573 742f
    5465 7374 3b01 000a 536f 7572 6365 4669
    6c65 0100 0954 6573 742e 6a61 7661 0c00
    0400 0501 0017 636f 6d2f 7869 6163 6877
    2f6a 766d 7465 7374 2f54 6573 7401 0010
    6a61 7661 2f6c 616e 672f 4f62 6a65 6374
    0021 0002 0003 0000 0000 0001 0001 0004
    0005 0001 0006 0000 002f 0001 0001 0000
    0005 2ab7 0001 b100 0000 0200 0700 0000
    0600 0100 0000 0300 0800 0000 0c00 0100
    0000 0500 0900 0a00 0000 0100 0b00 0000
    0200 0c
    

    观察ByteCode方法

    • JDK自带工具 javap
      javap命令,显示class信息,详细如下:
    C:\>javap D:\idea_gitlab_workspace\test111\out\production\test111\com\xiachw\singleton\test.class
    Compiled from "test.java"
    public class com.xiachw.singleton.test {
      public com.xiachw.singleton.test();
    }
    
    C:\>javap -v D:\idea_gitlab_workspace\test111\out\production\test111\com\xiachw\singleton\test.class
    Classfile /D:/idea_gitlab_workspace/test111/out/production/test111/com/xiachw/singleton/test.class
      Last modified 2020-3-16; size 279 bytes
      MD5 checksum 397d3394b815cace1c735cf9338410e3
      Compiled from "test.java"
    public class com.xiachw.singleton.test
      minor version: 0
      major version: 52
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #3.#13         // java/lang/Object."<init>":()V
       #2 = Class              #14            // com/xiachw/singleton/test
       #3 = Class              #15            // java/lang/Object
       #4 = Utf8               <init>
       #5 = Utf8               ()V
       #6 = Utf8               Code
       #7 = Utf8               LineNumberTable
       #8 = Utf8               LocalVariableTable
       #9 = Utf8               this
      #10 = Utf8               Lcom/xiachw/singleton/test;
      #11 = Utf8               SourceFile
      #12 = Utf8               test.java
      #13 = NameAndType        #4:#5          // "<init>":()V
      #14 = Utf8               com/xiachw/singleton/test
      #15 = Utf8               java/lang/Object
    {
      public com.xiachw.singleton.test();
        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
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/xiachw/singleton/test;
    }
    SourceFile: "test.java"
    
    • IDEA插件-jclasslib
      先把类编译一下,将光标放到类体上,选择菜单中的 view-> Show Bytecode With Jclasslib,帮你分析class的内容。
      在这里插入图片描述

    class文件各部分内容代表内容

    在这里插入图片描述

    xmind总结class文件各部分内容

    在这里插入图片描述

    展开全文
  • Class文件格式解析

    2013-08-23 22:01:05
    一、Java Class文件是什么 《The JavaTM Virtual Machine Specification》(Second Edtion)中有表述:Java Class文件由8位字节流组成,所有的16位、32位和64位数据分别通过读入2个、4个和8个字节来构造,多字节数据...
    一、Java Class文件是什么
    

    《The JavaTM Virtual Machine Specification》(Second Edtion)中有表述:Java Class文件由8位字节流组成,所有的16位、32位和64位数据分别通过读入2个、4个和8个字节来构造,多字节数据总是按照Big-endian顺序来存放,即高位字节在前(放在低地址)。每个Class文件都包含且仅包含一个Java类型(类或者接口)。

    或许,《The JavaTM Virtual Machine Specification》中的表述不够明确,那么我们可以参考一下《Inside the Java Virtual Machine》(Second Edtion)中的表述:Java Class文件特指以.class为后缀名的Java虚拟机可装载的文件。

    分析一下两者的表述,我觉得都不够全面、不够明确。我是这么定义的:Java Class文件就是指符合特定格式的字节流组成的二进制文件。这个特定的格式就是指第二节要讨论的Class文件格式,亦即在《The JavaTM Virtual Machine Specification》中定义的Class文件格式。从另一个角度来说,这个特定格式就是指JVM能够识别、能够装载的格式。为什么这么说呢?因为JVM在装载class文件时,要进行class文件验证,以保证装载的class文件内容符合正确的内部结构。这个内部结构指的就是这个特定格式,只要是符合这个特定格式的Class文件都是合法的、规范的Class文件,都是JVM能够装载的Class文件。如果觉得这样的表述还是不够明确,我只能建议你读完这篇文章之后再回头来理解看看了J

    为了讨论方便,在下文中将对这两个参考资料做个简记:

    1)《The Java Virtual Machine Specification》(Second Edtion)简记为《JVM Spec》(2nded)。

    2)《Inside the Java Virtual Machine》(Second Edtion) 简记为《Inside JVM》(2nded)。

    二、Java Class文件的格式

    在讲Class文件的格式之前,要介绍三个概念:

    1)数据类型:《JVM Spec》(2nded)中指出,Java Class文件的数据用自己定义的一个数据类型集来表示,即u1,u2,u4,分别用于表示一个无符号类型的、占1,2,4个字节的数据。在《Inside JVM》(2nded)一书中,作者把这个数据类型集称之为Class文件的基本类型,本人觉得比较形象,便于理解。所以,在本文中,我们也用基本类型来表示Java Class文件的数据。

    2)表:根据《JVM Spec》(2nded)中的定义,表(table)由项(定义见3)组成,用于几种Class文件结构中。《JVM Spec》(2nded)中指出,Java Class文件格式用一个类似于C结构的记号编写的伪结构来表示。这个伪结构指的就是这里的表,例如下面的ClassFile表就是这种伪结构的一个典型例子,下文中所有的表都是指这种伪结构的表。表的大小是可变的,这是因为它的组成部分项是可变的。注意;这里的可变是针对Class层次而言的,即在不同的Class文件中该项的大小可能不一样的,但是对于每一个具体的Class文件来说,这个项的大小又是一定的,因而这个表的大小也是一定的。那么,项为什么是可变的呢?请看下面的分析。

    3)项:描述Java Class文件格式的结构的内容称为项(items)。每个项都有自己的类型和名称。项的类型可能是基本类型,也可能是一个表的名字,这种项都是一些数组项。数组项的每一个元素都是一个表,这个表同顶层的ClassFile表一样,也都是一种伪结构,也都是由一些项构成的,而且这些表不一定是同一种格式的,因此数组项也可以看作一个可变大小的结构流J。这些表对于该数组项来说就是子项,当然子项可能还有子项(目前子项的深度最多就两层)。项的名称,没有什么好说的,就是《JVM Spec》(2nded)中指定的一些名称。另外,项也是有大小的,对于没有子项的项来说,其大小是固定的;对于有子项的项来说,其大小是可变的。在一个具体的Class文件中,一个可变项(数组)的大小都会在其前一项中指定,为什么会是这样的呢?因为《JVM Spec》(2nded)中就是这么定义的!在Class文件中,每个项按规范中定义好的顺序存储在Class文件中,相邻的项之间没有任何间隔,连续的项(数组)也是按顺序存储,不进行填充或者对齐,这样可以使Class文件紧凑。

    好了,我想这三个概念我已经解释地比较清楚了,下面开始正式解析Class文件的格式。

    首先要来解析一下ClassFile表结构,这是《JVM Spec》(2nded)中定义的Class文件最外层的结构,换言之,就是Class文件的格式。

    ClassFile表结构

        ClassFile {
            u4 magic;

            u2 minor_version;

            u2 major_version;

            u2 constant_pool_count;

            cp_info constant_pool[constant_pool_count-1];

            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];

        }

    ClassFile表结构由16个不同的项组成,其中的各项可以简要地分析如下:

    (1) magic

    每个Class文件的前4个字节被称为它的魔数(magic number): 0xCAFEBABE。魔数的作用在于:可以轻松地分辨出Java Class文件和非Java Class文件。(如果一个文件不是以0xCAFEBABE开头,它就肯定不是Java Class文件,因为它不符合规范J)。当Java还称为“Oak”的时候,这个魔数就已经定下来了,它预示了Java这个名字的出现。魔数的来历请大家自己查阅J

    (2) minor_version和major_version

    Class文件的下面4个字节包含了次、主版本号。通常只有给定主版本号和一系列次版本号后,Java虚拟机才能够读取Class文件。如果Class文件的版本号超出了Java虚拟机所能够处理的有效范围,Java虚拟机将不会处理该Class文件。例如J2SE5.0版本的虚拟机就不能执行由J2SE6.0版本的编译器编译出来的Class文件。

    (3) constant_pool_count

    版本号后面的项是constant_pool_count即常量池计数项,该项的值必须大于零,它给出该Class文件中常量池列表项的元素个数,这个计数项包括了索引为0的constant_pool表项,但是该表项不出现在Class文件的constant_pool列表中,因为它被保留为Java虚拟机内部实现使用了,因此常量池列表的元素个数constant_pool_count-1,各个常量池表项的索引值分别为1到constant_pool_count-1。

    注:在这里,有几个术语需要解释一下,常量池即为constant_pool,常量池列表就是指constant_pool[ ],常量池表项即指常量池列表中的某一个具体的表项(元素)。这些常量池表项的可能类型如下述的cp_type表所示:

    cp_type

    入口类型                                标志值 

    CONSTANT_Class                           7 

    CONSTANT_Fieldref                        9 

    CONSTANT_Methodref                       10 

    CONSTANT_InterfaceMethodref              11 

    CONSTANT_String                           8 

    CONSTANT_Integer                          3 

    CONSTANT_Float                            4 

    CONSTANT_Long                             5 

    CONSTANT_Double                           6 

    CONSTANT_NameAndType                      12 

    CONSTANT_Utf8                              1


    (4) constant_pool[ ]

    constant_pool_count项下面是constant_pool[ ]项,即常量池列表,其中存储了该ClassFile结构及其子结构中引用的各种常量,诸如文字字符串、final变量值、类名和方法名等等。在Java Class文件中,常量池表项是用一个cp_info结构来描述的,常量池列表就是由constant_pool_count-1个连续的、可变长度的cp_info表结构构成的constant_pool[ ]数组。为什么是constant_pool_count-1个constant_pool的原因,在上面已经解释了。每一个常量池表项都是一个变长结构,其通常格式如下所示:

    cp_info
    cp_info {
            u1 tag;
            u1 info[];
        }

    cp_info表的tag项是一个无符号的byte类型值,它表明了cp_info表的类型和格式,具体的tag类型见上表。

    需要说明的是,cp_info只是一个抽象的概念,在Class文件中,它表现为一系列具体的、形如CONSTANT_Xxxx_info的constant_pool结构,其具体的格式由cp_info表的tag项(即第一个字节)来确定。不同的cp_info表,其info[]项也是不一样的,例如,CONSTANT_Class_info表的info[]项为“u2 name_index”,而CONSTANT_Utf8_info表的info[]项为“u2 length; u1 bytes[length];”,显然,这两个cp_info表是不一样的,大小更是不一样的,因而常量池表项的大小是可变的。由于常量池列表中的每个常量池表项的结构是不一样,因此常量池列表的大小也是可变的。在Class文件中,常量池列表项是一个可变长度的结构流。

    由cp_info表以及cp_type表我们可以知道,若cp_info表中tag(标志)项的值为1时,当前的cp_info就是一个CONSTANT_Utf8_info表结构,若cp_info表中tag项的值为3,当前的cp_info就是一个CONSTANT_Integer_info表结构,其它情况类推。这些表的结构可以查阅《JVM Spec》(2nded)的第四章或者《Inside JVM》(2nded)的第六章。

    (5) access_flags

    紧接常量池后的两个字节称为access_flags,access_flags项描述了该Java类型的一些访问标志信息。例如,访问标志指明文件中定义的是类还是接口;访问标志还定义了在类或接口的声明中,使用了哪些修饰符;类和接口是抽象的还是公共的等等。实际上,access_flags项的值是Java类型声明中使用的访问标志符的掩码(mask,这里掩码指的是access_flags的值是所有访问标志值的总和,当然,未被使用的标志位在Class文件中都被设置为0。例如,若access_flags的值就是0x0001,就表示该Java类型的访问标志符是ACC_PUBLIC;若access_flags的值是0x0011,就表示该Java类型的访问标志符是ACC_PUBLIC和ACC_FINAL,因为只有这两个标志位的和才可能是0x0011;其它情况类推)。

    一个Java类型的所有access_flags标志符如下表所示:

    access_flags

    标志名称         值           含义

    ACC_PUBLIC     0x0001   声明为public,可以从它的包外访问

    ACC_FINAL      0x0010   声明为final,不允许有子类

    ACC_SUPER      0x0020   用invokespecial指令处理超类的调用

    ACC_INTERFACE  0x0200   表明是一个接口,而不是一个类

    ACC_ABSTRACT   0x0400   声明为abstract,不能被实例化

    需要说明的是,这是针对一个Java类型的访问标志符列表,有的标志符只有类可以使用,有的标志符只有接口才可以使用,详情请查阅《JVM Spec》(2nded)。

    (6) this_class

    接下来的两个字节为this_class项,其值为一个对常量池表项的索引,即它指向一个常量池表项,而且该常量池表项必须为CONSTANT_Class_info表的结构。该表有一个name_index项,该项将指向另一个常量池表项,该表项包含了该类或者接口的完全限定名称。

    (7) super_class

    紧接着this_class之后的两个字节是super_class项,该项必须是对常量池表项的一个有效索引或者值为0。如果super_class项的值为0,则该Class文件必须表示java.lang.Object类。如果super_class项的值不为0,则又分为两种情况,若该Class文件表示一个类,则super_class项必须是对常量池中该类的超类的CONSTANT_Class_info表项的索引,这个超类和它的任何超类都不能是一个final类;若该Class文件表示一个接口,则super_class项必须是对常量池中表示java.lang.Object类的一个CONSTANT_Class_info表项的索引。

    (8) interfaces_count和interfaces[ ]

    紧接着super_class项后面的两个字节是interfaces_count项,此项表示由该类直接实现或者由该接口所扩展的超接口的数量。

    紧接着interfaces_count项后面的是interfaces列表项,它包含了由该类直接实现或者由该接口所扩展的超接口的常量池索引,共计interfaces_count个索引。interfaces列表中的常量池索引按照该类型在源代码中给定的从左到右的顺序排列。

    (9) fields_count和fields[ ]

    接下来的是fields_count项,该项的值给出了fields列表项中的field_info表结构的数量,即表示了该Java类型声明的类变量和实例变量的个数总和。

    fields列表项包含了在该Java类型中声明的所有字段的完整描述。fields列表中的每个field_info表项都完整地表示了一个字段的信息,包括该字段的名称、描述符和修饰符等。这些信息有的放在field_info表中,如修饰符;有的则放在field_info表所指向的常量池中,如名字和描述符。同前面的分析,fields列表项也是一个变长结构。   

    需要说明的是,只有在该Java类型中声明的字段才可能在fields列表中列出,fields列表中不包括从超类或者超接口中继承而来的字段信息。

    (10) methods_count和methods[ ]

    在Class文件中,紧接着fields后面的是对在该Java类型中所声明的方法的描述。首先是methods_count项,它占两个字节长度,它的值表示对该Java类型中声明的所有方法的总计数。methods_count项后面是methods列表项,它由methods_count个连续的method_info表构成。每个method_info表都包含了与一个方法相关的信息,如方法名、描述符(即方法的返回值及参数类型)以及一些其它信息。如果一个方法既非abstract也非native,那么该method_info表将包含该方法局部变量所需的栈空间长度、为方法所捕获的异常表、字节码序列以及可选的行号表和局部变量表等信息。

    需要说明的是,只有在该Java类型中显式定义的方法才可能在fields列表中列出,fields列表中不包括从超类或者超接口中继承而来的方法信息。

    (11) attributes_count和attributes[ ]

    Class文件中最后的部分是属性(attribute),它给出了在该Java类型中所定义的属性的基本信息。首先是attributes_count项,它占两个字节长度,它的值表示在后续的attributes列表中的attributes_info表的总个数。每个attributes_info表的第一项都是对常量池中CONSTANT_Utf8_info表项的一个索引,该表给出了此属性的名称。

    需要说明的是,属性有很多种,在Class文件中的很多地方都出现了属性这一项,在顶层ClassFile表中有attributes属性项,在field_info表中也有attributes属性项,在method_info中也有attributes属性项,但是它们各有各的功能,详见上述分析。在《JVM Spec》(2nded)中,为ClassFile表结构的attributes列表项定义的唯一属性是SourceFile属性,为field_info表结构的attributes列表项定义的唯一属性是ConstantValue属性,为method_info表结构的attributes列表项定义的属性是Code属性和Exceptions属性。

    总而言之,Class文件格式是一个规范性的格式。这个规范指的就是,上面提到的这些表结构本身的规范性,以及这些表结构之间的包含关系的规范性。实际上,《JVM Spec》(2nded)中就是通过表和项这两个概念来组织Class文件的格式的。首先,ClassFile表就是Class文件最外层的结构,换言之,这就是Class文件的格式。其次,ClassFile表又是一些项组成的,这些项的内容都要符合《JVM Spec》(2nded)中定义的规范,具体来说,若这个项的类型是基本类型,该项的值要符合规范,例如magic项一定要是0xCAFEBABE,access_flags项的值一定要是有效的标志值等等;若这个项的类型是一个表名,即该项是一个数组项,那么该数组项列表中的每一个表项都要是一个合法的、规范的表,不能是一个规范中没有定义的新表,这就是包含关系的规范性,同样,列表项中的每个表项本身也都要是符合其规范定义的表项,例如常量池列表中的某个CONSTANT_Class_info表的name_index项不是对一个CONSTANT_Utf8_info表结构的索引,那么这个常量池的表项就不是一个合法的表项,因而这个常量池列表项就是不符合规范的,因而整个文件就是不符合规范的。

    展开全文
  • Class文件格式

    2017-08-29 13:39:17
    ClassFile { u4 magic; //魔术,4个字节,为0xCAFEBABE u2 minor_version; //次版本 u2 major_version; //大版本 u2 constant_pool_count; //常量池的个数,两个字节,代表后面会有多少个常量 cp_info ...

    ClassFile {
    u4 magic; //魔术,4个字节,为0xCAFEBABE
    u2 minor_version; //次版本
    u2 major_version; //大版本
    u2 constant_pool_count; //常量池的个数,两个字节,代表后面会有多少个常量
    cp_info constant_pool[constant_pool_count-1];
    u2 access_flags; //类的access类型
    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; //属性信息,以供fields和methods使用
    attribute_info attributes[attributes_count];
    }

    展开全文
  • 深入理解Java Class文件格式(一)

    万次阅读 多人点赞 2014-03-25 17:35:11
    本篇博客主要讲解能够被JVM识别, 加载并执行的class文件格式。 对于理解JVM和深入理解Java语言, 学习并了解class文件格式都是必须要掌握的功课。 原因很简单, JVM不会理解我们写的Java源文件, 我们必须把...
  • Java Class文件格式简析

    千次阅读 2018-07-04 20:41:17
    Java开发只需要编写Java代码之后通过javac命令将其编译成.class文件,.class文件可以被JVM虚拟机加载并执行。如果需要Java能够像动态语言那样编码,通常需要修改.class文件的内容,这种情况下了解.class文件的内部...
  • Class 文件格式详解

    2019-04-19 22:44:59
    Class 文件格式详解 Write once, run everywhere!,我们都知道这是 Java 著名的宣传口号。不同的操作系统,不同的 CPU 具有不同的指令集,如何做到平台无关性,依靠的就是 Java 虚拟机。计算机永远只能识别 0 和 1...
  • class文件格式

    2019-02-17 11:26:00
    ##2、.class文件结构 ###Class文件 一组以8位字节为基础单位的二进制流,其格式采用一种类似于c语言结构体的伪结构来存储,该伪结构只有两种数据类型:无符号数和表 无符号数属于基本的数据类型,以u1,u2,u4,u8...
  • 这个软件兼容很多文件格式,但对java编译后的.class文件就不听话,出现乱码,无论你更换怎样的编码格式,还是乱码,这时你需要插件才能解决这个问题,插件下载也是有要求,对应版本要下载对应的插件,不然就回出现...
  • beyond compare 对class文件反编译及比较

    万次阅读 2016-09-28 13:12:16
    首先打开beyond compare,选择工具-》文件格式,点击打开查看是否有一下选项(默认没有),有的话请打钩,没有则需要安装插件 打开网址:http://www.scootersoftware.com/download.php?zz=kb_moreformatsv4,先...
  • Java class文件分析工具 -- Classpy

    千次阅读 2017-10-19 14:33:00
    功能强大的图形化class文件分析工具!
  • 打包好的jar文件双击运行时报: Failed to load Main-Class manifest attribute from ......,这是由于未设置程序运行的入口程序导致的,可以将jar文件用WinRAR打开,展开META-INF文件夹,查看MANIFEST.MF文件,...
  • Error:(1, 1) 错误: 需要class, interface或enum

    万次阅读 多人点赞 2015-09-10 22:56:36
    造成这个error的原因是java文件编码格式不对, 比如可能是你之前这个文件是用GBK写的,后来复制到utf-8环境里编译,而文件里有些是隐藏的字符,很难找出来的。解决方法是在Notepad++新建一个空白文件,指定其编码...
  • 深入理解Java Class文件格式(六)

    万次阅读 多人点赞 2014-03-24 01:03:43
    经过前几篇文章, 终于将常量池介绍完了, 之所以花这么大的功夫介绍常量池, 是因为对于理解class文件格式,常量池是必须要了解的, 因为class文件中其他地方,大量引用了常量池中的数据项。 对于还不了解常量池的...
  • Class文件格式总结

    千次阅读 热门讨论 2014-03-29 01:59:52
    到此, 所有关于class文件格式的重要内容都已经讲解完了, 不敢说面面俱到, 但是敢说大部分重要的内容都包含在内了。前前后后用了9篇博客来专门讲解class文件结构, 为什么花那么多的时间和精力来介绍class文件呢?...
  • eclipse编译的class文件在哪里

    万次阅读 2017-11-08 11:39:52
    在eclipse中查找编译后的class
  • Class文件在Java体系结构中的位置和作用 在上一篇博客中, 大致讲解了Java虚拟机的体系结构和执行原理。 本篇博客主要讲解能够被JVM识别, 加载并执行的class文件格式。 对于理解JVM和深入理解...
  • 怎样加Java文件编译成class文件

    万次阅读 2018-06-25 10:26:29
    1.打开cmd,找到jdk安装的bin目录下,如图2,然后找到要编译的Java文件,我的Java文件在E:\workspaces\portal_one\JUnit_Test\src\main\java\com\baidu\test\dome\loader\Test.java;使用命令为Javac E:\workspaces...
  • jar包下MANIFEST.MF 中的 Class-Path 设置

    万次阅读 2012-08-29 12:52:18
    1. 基本格式  属性名称+:+空格+... Class-Path 当前路径是jar包所在目录,如果要引用当前目录下一个子目录中的jar包,使用以下格式  子目录/xxx.jar 子目录/yyy.jar  技巧:多个jar包的引用,可
  • eclipse查看jar包中class的中文注释乱码问题的解决

    万次阅读 多人点赞 2014-11-10 12:02:02
    将Eclipse的Preferences中的General》ContentTypes中的Java Class File和Text的default encoding都设置成了UTF-8(或者是其他你需要设置的编码格式) 重新关联一次!我把源码jar包换了地方重新关联一次就OK了。 ...
1 2 3 4 5 ... 20
收藏数 3,203,269
精华内容 1,281,307
关键字:

class文件格式