JVM调优篇之JVM基础入门AND字节码文件解读

目录

    • Java程序编译
    • class文件内容
    • 常量池
    • 附录-访问标识表
    • 附录-常量池类型列表

Java程序编译

Java文件通过编译成class文件后,通过JVM虚拟机解释字节码文件转为操作系统执行的二进制码运行。

规范

Java虚拟机有自己的一套规范,遵循这套规范,任何形式的语言都可以在JVM上运行,前提是编译成class文件,此规范相见oracle官网文档

实现

JVM虚拟机落地实现有很多,常见的有:

  • Hotspot,使用最热门的JVM
  • OpenJ9,IBM开发
  • MicroSoft JVM 微软开发
  • TaobaoVM 淘宝开发
  • azul zing VM 垃圾回收行业标杆,最快

class文件内容

从上图内容可看出class文件包以下几个方面内容:

  • 魔数(magic number)占4个字节,固定的值0xcafebabe,主要来校验class文件。
  • version 版本号,分为小版本号minor version和大版本号major version,各占两个字节。
  • 常量池信息(constant_pool),具体的各种常量信息,字符串,类名,方法名,字段名等。
  • 访问标识(access_flag),2个字节描述类与接口的修饰符,有几个常见的常量值见附录-访问标识
  • 当前类(this_class
  • 当前类的父类(super_class
  • 具体的接口信息(interfaces
  • 具体的属性信息(fileds
  • 具体的方法信息(methods
  • 其它附加属性信息(attributes

更具体的内容如下:

项目 Value
Magic Number 魔数(CAFE BABE)
Minor Number 次版本号
Major Number 主版本号
constant_pool_count 常量池数量
constant_pool 常量池具体实现,是一种表
access_flag 访问标识
this_class 当前类名
super_class 父类名称
interfaces_count 接口数量
interfaces 具体实现的接口信息
fileds_count 属性数量
fileds 具体属性信息
methods_count 方法数量
methods 具体方法的信息
attributes_count 其它附加属性的数量
attributes 其它附加属性具体信息

现在来看具体示例来看上面的代表是什么意思,准备一个简单的类:

java 复制代码
public class ByteCode01 {
    public ByteCode01() {
    }
}

编译之后的字节码文件:

class文件中就是一个二进制字节流,非0即1,数据类型有五种,u1,u2,u4,u8和_info表类型

上述这种文件需要借助工具来分析具体内容,在idea安装jclasslib插件看Java文件编译成class文件信息,选中编译后的class文件,如下图所示:

访问标识是固定的值,通过位运算得出的0x0021既代表public又代表super0x00210x00010x0020位与运算),详见附录-访问标识表

更直观的表现:

常量池

本类索引即当前类名(this_class),cp_infoconstant_pool的表类型,#2是第二张表,cp_info #2代表常量池第二张表,存的是对cp_info #14的引用,cp_info #14存的是具体的字符串值,就是当前类的类名。


class文件中都有属于自己的常量池,常量池包含类型列表,来存储类、方法、字段、接口等信息,以及各种字面量,通过解析常量池可以访问这些字符串信息。比如上图出现的CONSTANT_Utf8_infoCONSTANT_Class_info等详见文末常量池类型列表

着重看下CONSTANT_Utf8_info,它用来存储 UTF-8 编码的字符串,相当于一张常量池表,看一下它的具体结构:

字段名 字节数 描述
tag 1 CONSTANT_Utf8_info的常量类型是1(其余的见文末常量池类型列表
length 2 u2(2 字节无符号数) 类型字段,表示 bytes 部分字节长度,以字节为单位的
bytes length 实际字符串数据,采用 UTF-8 编码显示

比如

java 复制代码
public class Test {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

字符串 Hello, World!,会以 CONSTANT_Utf8_info 类型存储在常量池中,对应的二进制内容或许是:

mathematica 复制代码
tag      = 0x01 (标识 CONSTANT_Utf8_info)
length   = 0x000D (字符串的字节长度为 13)
bytes    = 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 ("Hello, World!" 的 UTF-8 编码)

常量池通常分为下面几种常量值类型:

类型 标志(tag) 描述
CONSTANT_Utf8_info 1 UTF-8编码的字符串
CONSTANT_Integer_info 3 整型字面量
CONSTANT_Float_info 4 浮点型字面
CONSTANT_Long_info 5 长整型字面量
CONSTANT_Double_info 6 双精度浮点型字面量
CONSTANT_Class_info 7 类或接口的符号引用
CONSTANT_String_info 8 字符串类型字面量
CONSTANT_Fieldref_info 9 字段的符号引用
CONSTANT_Methodref_info 10 类中方法的符号引用
CONSTANT_InterfaceMethodref_info 11 接口中方法的符号引用
CONSTANT_NameAndType_info 12 字段或方法的部分符号引用
CONSTANT_MethodHandle_info 15 表示方法句柄
CONSTANT_MethodType_info 16 表示方法类型
CONSTANT_InvokeDynamic_info 18 表示一个动态方法调用点

附录-访问标识表

项目 Value
ACC_PUBLIC 0x0001 是否是public类型
ACC_FINAL 0x0010 是否是NULL
ACC_SUPER 0x0020 该标志必须为真
ACC_INTERFACE 0x0200 是否为接口
ACC_ABSTRACT 0X0400 是否是接口或者抽象类
ACC_SYNTHETIC 0x1000 编译器自动生成,非用户代码产生
ACC_ANNOTATION 0x2000 是否为注解
ACC_ENUM 0x4000 是否为枚举

附录-常量池类型列表

常量类型 tag值 描述
CONSTANT_Utf8_info 1 用于存储 UTF-8 编码的字符串
CONSTANT_Integer_info 3 用于存储 4 字节的整型字面量(int
CONSTANT_Float_info 4 用于存储 4 字节的浮点型字面量(float
CONSTANT_Long_info 5 用于存储 8 字节的长整型字面量(long
CONSTANT_Double_info 6 用于存储 8 字节的双精度浮点型字面量(double
CONSTANT_Class_info 7 用于存储类或接口的符号引用,引用 CONSTANT_Utf8_info 中的类名
CONSTANT_String_info 8 用于存储字符串字面量,引用 CONSTANT_Utf8_info 中的字符串内容
CONSTANT_Fieldref_info 9 用于存储字段的符号引用,引用类和字段的描述信息
CONSTANT_Methodref_info 10 用于存储类中方法的符号引用,引用类和方法的描述信息
CONSTANT_InterfaceMethodref_info 11 用于存储接口中方法的符号引用,引用接口和方法的描述信息
CONSTANT_NameAndType_info 12 用于描述字段或方法的名称和类型,引用名称(Utf8)和描述符(Utf8
CONSTANT_MethodHandle_info 15 用于存储对方法句柄的引用(invokedynamic 指令用)
CONSTANT_MethodType_info 16 用于存储方法类型的符号引用,指向方法描述符(Utf8
CONSTANT_Dynamic_info 17 用于存储动态调用点的信息(JDK 11 引入,支持动态常量)
CONSTANT_InvokeDynamic_info 18 用于存储动态方法调用点的信息,引用引导方法和动态调用名称
CONSTANT_Module_info 19 用于存储模块的符号引用(JDK 9 引入)
CONSTANT_Package_info 20 用于存储包的符号引用(JDK 9 引入)
相关推荐
1.01^10007 小时前
[5-01-01].第04节:初识字节码文件 - 字节码文件作用
jvm
找不到、了10 小时前
JVM核心知识整理《1》
jvm
L.EscaRC12 小时前
面向 Spring Boot 的 JVM 深度解析
jvm·spring boot·后端
学到头秃的suhian1 天前
JVM-类加载机制
java·jvm
NEFU AB-IN1 天前
Prompt Gen Desktop 管理和迭代你的 Prompt!
java·jvm·prompt
唐古乌梁海2 天前
【Java】JVM 内存区域划分
java·开发语言·jvm
众俗2 天前
JVM整理
jvm
echoyu.2 天前
java源代码、字节码、jvm、jit、aot的关系
java·开发语言·jvm·八股
代码栈上的思考2 天前
JVM中内存管理的策略
java·jvm
thginWalker2 天前
深入浅出 Java 虚拟机之进阶部分
jvm