• JVM-字节码


    JVM 字节码

    Java 之所以可以“一次编译,到处运行”,一是因为 JVM 针对各种操作系统、平台都进行了定制,二是因为无论在什么平台,都可以编译生成固定格式的字节码(.class 文件)供 JVM 使用。

    .class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项严格按照顺序紧凑地排列在 .class 文件中,中间没有添加任何分隔符。整个 .class 文件本质上就是一张表。

    字节码

    什么是字节码

    之所以被称之为字节码,是因为字节码文件由十六进制值组成,而 JVM 以两个十六进制值为一组,即以字节为单位进行读取。在 Java 中一般是用 javac 命令编译源代码为字节码文件,一个.java 文件从编译到运行的示例如下图所示。

     对于开发人员,了解字节码可以更准确、直观地理解 Java 语言中更深层次的东西,比如通过字节码,可以很直观地看到 Volatile 关键字如何在字节码上生效。另外,字节码增强技术在 Spring AOP、各种 ORM 框架、热部署中的应用屡见不鲜,深入理解其原理对于我们来说大有裨益。除此之外,由于 JVM 规范的存在,只要最终可以生成符合规范的字节码就可以在 JVM 上运行,因此这就给了各种运行在 JVM 上的语言(如 Scala、Groovy、Kotlin)一种契机,可以扩展 Java 所没有的特性或者实现各种语法糖。理解字节码后再学习这些语言,可以“逆流而上”,从字节码视角看它的设计思路,学习起来也“易如反掌”。

    字节码结构

    .java 文件通过 javac 编译后将得到一个.class 文件

    (1)魔数(Magic Number)

    每个 .class 文件的头 4 个字节称为 魔数(magic number),它的唯一作用是确定这个文件是否为一个能被虚拟机接收的 .class 文件。魔数的固定值为:0xCAFEBABE

    有趣的是,魔数的固定值是 Java 之父 James Gosling 制定的,为 CafeBabe(咖啡宝贝),而 Java 的图标为一杯咖啡。

    (2)版本号(Version)

    版本号为魔数之后的 4 个字节,前两个字节表示次版本号(Minor Version),后两个字节表示主版本号(Major Version)。

    (3)常量池(Constant Pool)

    紧接着主版本号之后的字节为常量池入口。

    常量池主要存放两类常量:

    • 字面量 - 如文本字符串、声明为 final 的常量值。
    • 符号引用
      • 类和接口的全限定名(Fully Qualified Name)
      • 字段的名称和描述符(Descriptor)
      • 方法的名称和描述符

    常量池整体上分为两部分:常量池计数器以及常量池数据区:

    • 常量池计数器(constant_pool_count) - 由于常量的数量不固定,所以需要先放置两个字节来表示常量池容量计数值。
    • 常量池数据区 - 数据区是由(constant_pool_count-1)个 cp_info 结构组成,一个 cp_info 结构对应一个常量。

    (4)访问标志

    紧接着的 2 个字节代表访问标志(access_flags),这个标志用于识别一些类或者接口的访问信息,描述该 Class 是类还是接口,以及是否被 publicabstractfinal 等修饰符修饰。

    (5)当前类名

    访问标志后的 2 个字节,描述的是当前类的全限定名。这两个字节保存的值为常量池中的索引值,根据索引值就能在常量池中找到这个类的全限定名。

    (6)父类名称

    当前类名后的 2 个字节,描述父类的全限定名,同上,保存的也是常量池中的索引值。

    (7)接口信息

    父类名称后为 2 字节的接口计数器,描述了该类或父类实现的接口数量。紧接着的 n 个字节是所有接口名称的字符串常量的索引值。

    (8)字段表

    字段表用于描述类和接口中声明的变量,包含类级别的变量以及实例变量,但是不包含方法内部声明的局部变量。字段表也分为两部分,第一部分为两个字节,描述字段个数;第二部分是每个字段的详细信息 fields_info。

    (9)方法表

    字段表结束后为方法表,方法表也是由两部分组成,第一部分为两个字节描述方法的个数;第二部分为每个方法的详细信息。方法的详细信息较为复杂,包括方法的访问标志、方法名、方法的描述符以及方法的属性

    (10)附加属性表

    字节码的最后一部分,该项存放了在该文件中类或接口所定义属性的基本信息。

     
    属性名称使用位置含义
    Code 方法表 Java代码编译成的字节码指令
    ConstantValue 字段表 final关键字定义的常量值
    Deprecated 类、方法表、字段表 被声明为deprecated的方法和字段
    Exceptions 方法表 方法排除的异常
    InnerClass 类文件 内部类列表
    LineNumberTable Code属性 Java源代码的行号和字节码指令的对应关系
    LocalVariableTable Code属性 方法的局部变量描述
    SourceFile 类文件 源文件名称
    Synthetic 类、方法表、字段表 标识方法或字段为编译器自动生成的
  • 相关阅读:
    Z遮罩层完全覆盖页面
    页面加载完成时
    文字超出不换行,用省略号表示
    去掉最后一个元素的边线
    电话点击即可拨打
    制作对话的三角形
    active在iphone上不起作用
    jquery选择后代以及toggle,toggleClass用法
    button点击变换颜色时出现一个蓝色边框
    表格边框的实现
  • 原文地址:https://www.cnblogs.com/turbosha/p/13252186.html
Copyright © 2020-2023  润新知