zoukankan      html  css  js  c++  java
  • 2.class文件详解

    我们可任意打开一个Class文件(使用Hex Editor,sublime等工具打开),内容如下(内容是16进制):
     
     
     
    开头的4个字节 代表的是魔数 它的唯一作用是确定这个文件是否是一个能被虚拟机接收的Class文件。后面4个字节代码的是使用的jdk版本号。其中前2个字节代码次版本号,后面2个字节代码主版本号。
    JDK版本号信息对照表:
    常量池计数器
    常量池是class文件中非常重要的结构,它描述着整个class文件的字面量信息。
    常量池是由一组constant_pool结构体数组组成的,而数组的大小则由常量池计数器指定。
    常量池计数器constant_pool_count 的值 =constant_pool表中的成员数+ 1。
    constant_pool表的索引值只有在大于 0且小于constant_pool_count时才会被认为是有效的。
     
    有很多可以观察ByteCode的方法:
    1.javap -v 命令
    2.JClassLib ----IDEA的插件之一,非常方便
    注意事项:
    常量池计数器默认从1开始而不是从0开始:
    当constant_pool_count = 1时,常量池中的cp_info个数为0;当constant_pool_count为n时,常量池中的cp_info个数为n-1。
    原因:
    在指定class文件规范的时候,将索引#0项常量空出来是有特殊考虑的,这样当:某些数据在特定的情
    况下想表达“不引用任何一个常量池项”的意思时,就可以将其引用的常量的索引值设置为#0来表示。
    常量池数据区
    访问标志
    访问标志,access_flags 是一种掩码标志,用于表示某个类或者接口的访问权限及基础属性。
    类索引
    类索引,this_class的值必须是对constant_pool表中项目的一个有效索引值。constant_pool表在这个索引处的项必须为CONSTANT_Class_info 类型常量,表示这个 Class 文件所定义的类或接口。
    父类索引
    父类索引,对于类来说super_class的值必须为0或者是对constant_pool表中项目的一个有效索引值。
    如果它的值不为0,那constant_pool 表在这个索引处的项必须为CONSTANT_Class_info类型常量,表示这个Class文件所定义的类的直接父类。
    当前类的直接父类,以及它所有间接父类的access_flag中都不能带有ACC_FINAL标记。对于接口来说,它的Class文件的super_class项的值必须是对constant_pool表中项目的一个有效索引值。constant_pool表在这个索引处的项必须为代表java.lang.ObjectCONSTANT_Class_info类型常量 。
    如果Class文件的super_class的值为0 那这个Class文件只可能是定义的是java.lang.Object类,只有它是唯一没有父类的类.
    接口计数器
    接口计数器,interfaces_count的值表示当前类或接口的【直接父接口数量】。
    接口信息数据区
    接口表,interfaces[]数组中的每个成员的值必须是一个对constant_pool表中项目的一个有效索引值, 它的长度为 interfaces_count
    每个成员interfaces[i] 必须为CONSTANT_Class_info类型常量,其中 【0 ≤ i <interfaces_count】。
    interfaces[]数组中,成员所表示的接口顺序和对应的源代码中给定的接口顺序(从左至右)一样,即interfaces[0]对应的是源代码中最左边的接口。
    字段计数器
    字段计数器,fields_count的值表示当前 Class 文件 fields[]数组的成员个数。
     fields[]数组中每一项都是一个field_info结构的数据项,它用于表示该类或接口声明的【类字段】或者【实例字段】。
    字段信息数据区
    字段表,fields[]数组中的每个成员都必须是一个fields_info结构的数据项,用于表示当前类或接口中某个字段的完整描述。 
    fields[]数组描述当前类或接口声明的所有字段,但不包括从父类或父接口继承的部分。
    方法计数器
    方法计数器, methods_count的值表示当前Class 文件 methods[]数组的成员个数。Methods[]数组中每一项都是一个 method_info 结构的数据项。
    方法信息数据区
    方法表,methods[] 数组中的每个成员都必须是一个 method_info 结构的数据项,用于表示当前类或接口中某个方法的完整描述。
    如果某个method_info 结构的access_flags 项既没有设置 ACC_NATIVE 标志也没有设置ACC_ABSTRACT 标志,那么它所对应的方法体就应当可以被 Java 虚拟机直接从当前类加载,而不需要引用其它类。
    method_info结构可以表示类和接口中定义的所有方法,包括【实例方法】、【类方法】、【实例初始化方法】和【类或接口初始化方法】。
    methods[]数组只描述【当前类或接口中声明的方法】,【不包括从父类或父接口继承的方法】。
    属性计数器
    属性计数器,attributes_count的值表示当前 Class 文件attributes表的成员个数。attributes表中每一项都是一个attribute_info 结构的数据项。
    属性信息数据区
    属性表,attributes 表的每个项的值必须是attribute_info结构。
    Java 7 规范里,Class文件结构中的attributes表的项包括下列定义的属性: 
    InnerClasses EnclosingMethod  Synthetic SignatureSourceFileSourceDebugExtensionDeprecatedRuntimeVisibleAnnotations RuntimeInvisibleAnnotations以及BootstrapMethods属性。
    对于支持 Class 文件格式版本号为 49.0 或更高的 Java 虚拟机实现,必须正确识别并读取attributes表中的SignatureRuntimeVisibleAnnotationsRuntimeInvisibleAnnotations属性。
    对于支持Class文件格式版本号为 51.0 或更高的 Java虚拟机实现,必须正确识别并读取 attributes表中的BootstrapMethods属性。
    Java 7 规范 要求任一 Java 虚拟机实现可以自动忽略 Class 文件的 attributes表中的若干 (甚至全部) 它不可识别的属性项。
    任何本规范未定义的属性不能影响Class文件的语义,只能提供附加的描述信息。
     
  • 相关阅读:
    ubuntu16.04使用anaconda创建python虚拟环境
    Ubuntu16.04里安装anaconda3后将python第三方包安装到指定目录下
    conda把包安装到当前激活的环境中
    ubuntu修改环境变量
    conda安装tensorflow
    ASP VNext 开源服务容错处理库Polly
    EntityFramework实现指定字段的通用赋值
    NET流行高性能JSON框架-Json.NET
    .NET网站国际化策略
    软件开发工作流-GitFlow
  • 原文地址:https://www.cnblogs.com/wangyang1991/p/13256105.html
Copyright © 2011-2022 走看看