类文件结构

一.class类文件结构

    class文件是一组8位字节二进制流。

    分为两种数据结构,无符号数和表。

    无符号数: 用u1,u2,u4,u8代表1,2,4,8个字节。   用来描述数字、索引引用、数量值、或者utf-8字符串。

    表:多个无符号数或者其它表构成,习惯以_info结尾。

    表中各个数据项的含义

    1.magic  一串固定的值标示这是java文件  ,版本,表示它所对应java版本

    2.常量池

        u2类型来标示有多少个常量,它是从1开始计数的。

        常量池有以下两种类型,   字面量(string, 声明为final的常量值)   , 符号引用

        符号引用包含以下三种类型:

        a.类和接口的权限定名

        b.字段的名称和描述符

        c.方法的名称和描述符

        比如constant_class_info类型,    它有一个u1类型的tag,标示它是什么样的数据。name_index是一个索引值,指向常量池中的另外一条常量。

        而指向的这一条常量,是一个constant_string_info,它由 tag  length  bytes组成,构成了一个字符串,用以标示class的名称。

        class  -->    string   -->   "具体的类的名称"

      3.访问标志

        access_flags 标示这个class 是class还是interface ,是public还是private等等

    4.类索引,父类索引,接口索引集合

        类索引和父类索引,他们都是指向一个 constant_string_info 类型的常量,最终标示其类的全名。

        接口索引集合第一项为 数量,后面跟着偏移地址。

    5.字段表集合

        包含 类级变量和 实例级变量,不包括方法内的变量。

        access_flags:描述字段的访问类型 private public等miaoshufu

        name_index、descriptor_index:分别是简单名称和描述符,都是对常量池的引用。

        简单名称:是指没有类型和参数修饰的方法或者字段名称,   如  inc() 便是  inc。

        描述符:描述其参数以及返回值  如  string[][]  为  [[java/lang/string      int  aaa(char[] s,int i,int j)描述符为([CII)I参数类型在前,返回值类型在后。

        attributes_count:

        attributes:

    6.方法表集合

        access_flags:public、private、synchronized等

        name_index,descriptor_index:描述方法的参数和返回值

        *方法内的代码被编译成了code

    7.属性表集合

        class文件,属性表,方法表都可以有自己的属性表集合。

        有以下属性:

        1.code  用于方法表  

        2.constantvalue  字段表

        3.deprecated  类,方法表 ,字段表,被声明为 deprecated 的方法和字段

        4.exceptions 方法表,抛出异常

        5.EnclosingMethod  类文件,匿名类或者局部类

        6.innerClasses 类文件 内部类

        7.LineNumberTable  code属性  行号与字节码的关系  

        。。。以下省略五百字

        code属性:

            attributle_name_index/attribute_length:指向constant_utf8_info,常量值固定为code  ,length为长度,分别为u2 u4类型,一共六个字节。

            max_stack,操作数栈最大深度,这样虚拟机在分配栈帧时,不会超过这个值。

            max_locals,局部变量表所需要的存储空间,代表了局部变量所需要的存储空间。每个slot可以存储32位的变量,double和long需要占用两个slot,并非有多少个变量就需要杜少slot,因为变量过期,就可以重用。

            code_length, 用来存储编译生成的字节码指令,每个指令是一个u1类型的单字节,取值为 0x00 - 0xff,最大长度不超过 65535.

            code,最重要的属性,其中stack为第几个方法,locals为局部变量的数目,args_size为传入参数的数目。在非static方法内,所有的arg_size至少为1,因为要传入this,也因此,即使没有局部变量,locals的数目也会等于该对象的属性。

            异常处理表,并非必须存在,有start_pc,end_pc来标示try 哪一段代码,handler_pc进行处理,catch_type指向一个CONSTANT_Class_info的索引。

        Exceptions属性

            Exceptions描述的是列举出来方法中可能抛出的受查异常。其中number_of_exceptions标示错误的数量,exception_index_talbe是一个数量和number_of_exception相同的table,每一项都指向常量池中的class_info实例。

        LineNumberTable

            通过一个start_pc和line_number来对应字节码行号和源码行号,主要用于debug。

        LocalVariableTable属性

            描述栈帧中局部变量表与源码中定义的变量之间的关系

            local_variable_info代表一个栈帧与变量之间的关联,结构如下

            start_pc、lenght   两个变量共同描述了字节偏移量和它的覆盖范围

            name_index和descriptor_index 都指向常量池中UTF-8_info的索引,代表局部变量的名称和局部变量的描述符。

            index是这个局部变量在栈帧局部变量表中Slot的位置

        SourceFIle属性

            记录生成这个class的源码文件名称

        ConstantValue属性

            通知虚拟机自动为静态变量赋值,被static修饰的变量(即类变量)才可以使用这项属性。

            实例变量,在<init>中赋值,而类变量,在<cinit>中赋值。

            而用final 和 static修饰,才可以用constantvalue来赋值。

            它也拥有一个constantvalue_index,代表了常量池中一个字面量常量的引用,有可能是long  float double string

        innerClasses属性

            记录内部类和宿主类之间的联系,如果类有内部类,则会生成innerClasses属性。

            由  attribute_name_index  attribute_lenght  number_of_classes(一共有多少个匿名内部类)  inner_classes类型为inner_classes_info个数与number_of_classes相当,描述内部类信息

            inner_classes_info

            inner_class_info_index和outer_class_info_index都指向了常量池中的CONSTANT_Class_info型常量的索引,表明了内部类和宿主类的符号引用。

            inner_name_index指向常量池中UTF-8型常量的索引,如果为匿名内部类,则为0.

            inner_class_access_flags是匿名内部类的访问标志。有 public  private  等等。

        Deprecated和Synthetic属性

            Deprecated为@deprecated产生的,Synthetic为编译器添加,为编译器自动产生。

            他们的attribute_length为0x00000000因为灭有任何属性值需要设置。

        StackMapTable属性

            包含多个栈映射帧,都代表了一个字节码偏移量,用于标示执行到该字节码是局部变量表和操作数栈的验证类型。

        Signature属性

             由于java的泛型编译后会被擦除掉,所以无法通过反射来获取真正的泛型,所以Signature用来实现此功能。

             signature_index是一个对常量池的索引,表示类签名,方法类型,或字段类型。

        BootstrapMethods属性

            包含bootstrap_method方法,为引导方法

二.字节码指令

        虚拟机指令可以分为以下九种

        1.加载和存储指令   

            将一个局部变量加载到操作栈     将数值从操作数栈存储到局部变量表     将常量加载到操作数栈  扩产个局部变量表的访问索引

        2.运算指令  加减乘除 按位与或取反等  

        3.类型转换指令  int->long  float double  long->float double flat->double

        4.对象创建与访问指令  创建对象new  创建数组newarray 访问类字段

        5.操作数栈管理 pop  push等操作

        6.控制转移指令 跳转执行 如if等

        7.方法调用和返回指令 

        8.异常处理

        9.同步指令                       

转载于:https://my.oschina.net/vqishiyu/blog/1922721

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值