zoukankan      html  css  js  c++  java
  • java7:核心技术与最佳实践读书笔记——字节代码格式

    一般流程:开发人员写出java源代码(.java) ->  javac(编译器) -> java字节代码(.class) -> 加载 -> java虚拟机(jvm)运行。

    1、常见java源代码的字节代码表现形式

    • 包名: com.java.sample -> com/java/sample
    • 基本类型:byte、char、double、float、int、long、boolean -> B、C、D、F、I、J、S、Z
    • 引用类型:统一使用 "L" 前缀和 ";" 后缀,如:java.lang.String -> Ljava/lang/String;
    • 数组类型:采用  "[" 前缀,如:double[] -> [D,double[][] -> [[D
    • 空类型:void -> V
    • 方法:int calculate(String str) -> 方法的类型描述符:(Ljava/lang/String;)I ,还需要包含方法的签名信息

    2、基本格式

    字节代码是一个连续的字节流,其中每个部分的含义不同。字节数据分为定长和不定长,不定长会在数据最前面给出长度;定长数据则有u1、u2、u4等类型,即1字节、2字节、4字节等。多字节顺序采用大端表示。
    u4 魔法数 字节代码格式的标识符,固定为0xCAFEBABE,“咖啡宝贝”,java名称的由来
    u2 小版本号  
    u2 大版本号 jdk7版本号:51.0 -> 0x0000 0033(4个字节)
    u2 常量池中常量的个数再加1 包含基本类型和字符串常量值、类、接口和域的名称,每个常量的类型和所占用的字节数是不同的。常量池是一张表,定义了常量的序号和常量的值。
    cp_info 常量池内容的数组 cp_info结构表示每个常量的具体定义
    u2 访问控制标记和属性修饰符 每个标记或者修饰符对应一个比特位,比如:public -> 0x0001 , private -> 0x0002, final -> 0x0010, interface -> 0x0200, abstract -> 0x4000, synthetic -> 0x1000(由编译器生成,源码中无此关键字),annotation -> 0x2000等
    u2 当前类或接口信息的常量池序号  
    u2 父类或者父接口信息的常量池序号 如果当前类为java.lang.Object,则两个字节值为0, 因为Object没有父类
    u2 实现接口的个数  
    u2 域的个数  
    field_info 包含域信息的数组  
    u2 方法的个数  
    method_info 包含方法信息的数组  
    u2 属性的个数  
    attribute_info 包含属性信息的数组  
     
    3、常量池的结构
    每个常量的起始字节标明常量的类型,该字节称为标签(如:CONSTANT_String_info、CONSTANT_Class_info);这个字节之后是包含常量内容的若干个字节(CONSTANT_Utf8_info)。
     
    java基本常量的定义方式:
    • 字节代码中只包含基本类型:int、long、float、double的对应表示,其他基本类型都可用int来表示。
    • int、float标签后面跟着4个字节的数据,long和double标签后面跟着8个字节的数据。
    • CONSTANT_Utf8_info表示一个使用修改后的UTF-8格式表示的字符串序列,标签后的两个字节表示序列的长度,紧接着是序列的内容。如:this -> 0x0004<this> //this为4个字节长,序列内容为“this”
    • CONSTANT_String_info直接引用CONSTANT_Utf8_info常量,值包含一个对应的常量池中的序号。如:String:cp_info_#17 //17号常量池序号 -> 0x0005<hello>
    • CONSTANT_Class_info表示类和接口,在标签后面是类或者接口的全名对应的CONSTANT_Utf8_info常量的序号。如:Class name:cp_info_#2 //17号常量池序号 -> 0x0010<java/lang/Object>
    • 类或接口的域和方法,由两类常量来共同表示:
      • 第一类常量CONSTANT_NameAndType_info表示域和方法的名称和类型,分别由两个CONSTANT_Utf8_info常量来表示
    Name cp_info_#7<str>
    Descriptor cp_info_#8<Ljava/lang/String;>
     
      • 第二类常量表示域和方法与类或接口的对应关系。
        • CONSTANT_Fieldref_info:域信息
        • CONSTANT_Methodref_info:类方法信息
        • CONSTANT_InterfaceMethodref_info:接口方法信息
        • 上面三类结构相似,标签之后分别是表示所在类或接口的CONSTANT_Class_info常量和表示名称与类型的CONSTANT_NameAndType_inifo常量的序号。如:
    Class name cp_info_#1<test/TestClass>
    Name and type cp_info_#19<str : Ljava/lang/String;>

    4、域结构
    u2 访问控制标记和属性修饰符
    u2 名称的常量的序号
    u2 类型描述符的常量的序号
    u2 属性的个数
    attribute_info 包含属性信息的数组
    如:private int value 域值     
    name cp_info_#5<value>
    Descritpor: cp_info_#6<I>
    Acess flags: 0x0002[private]
    省略method_info,因为与field_info结构相同
    如:public int getValue()
    name cp_info_#24<getValue>
    Descriptor cp_info_#25<()I>
    Acess flags 0x0001[ public ]
     
    5、属性
    介绍完了类、域和方法等基本信息的表示,接下来其他的信息都由属性来表示,本质上就是一个名值对。
    u2 属性名称对应的常量序号
    u4 属性值得字节数组的长度
    不定长 属性值得字节数组

     

  • 相关阅读:
    操作系统_3:linux教程列表
    MongoEngine 查询语法
    Spark_1:教程索引
    软件需求十步走之阅读笔记03
    软件需求十步走之阅读笔记02
    软件需求十步走之阅读笔记01
    暑期学习四
    暑期学习三
    暑期学习二
    暑期学习一
  • 原文地址:https://www.cnblogs.com/linzhanfly/p/6640401.html
Copyright © 2011-2022 走看看