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 引入)
相关推荐
王佑辉7 小时前
【jvm】java对象的访问定位
jvm
不止会JS9 小时前
JVM详解:垃圾回收机制
jvm
guihong0049 小时前
JAVA面试题、八股文学习之JVM篇
java·jvm·学习
gogo_hua10 小时前
JVM系列之OOM观测准备
java·大数据·jvm
柯3491 天前
GC垃圾回收
java·jvm·垃圾回收
王佑辉1 天前
【jvm】执行引擎是做什么
jvm
平头哥在等你1 天前
C语言简答题答案
java·c语言·jvm
zhuzhihongNO11 天前
JVM(JAVA虚拟机)内存溢出导致内存不足,Java运行时环境无法继续
java·开发语言·jvm·内存溢出·jvm内存溢出