首页 > 其他分享 >JVM类文件结构

JVM类文件结构

时间:2024-07-15 15:10:10浏览次数:13  
标签:info 文件 CONSTANT 常量 class 索引 JVM public 结构

  • .java源文件
package test.JVM;

public class Test {
    public static void main(String[] args) {
        System.out.println("haha");
    }
}
  • 十六进制查看.class文件

魔数


第一行中有一串特殊的字符 CAFEBABE,它就是一个魔数,是 JVM 识别 class 文件的标志,JVM 会在验证阶段检查 class 文件是否以该魔数开头,如果不是则会抛出 ClassFormatError

版本号


紧跟着魔数后面的四个字节 0000 0034 分别表示副版本号和主版本号。也就是说,主版本号为 52(0x34 的十进制),也就是 Java 8 对应的版本号,副版本号为 0。

常量池


紧跟在版本号之后的是常量池,它包含了类、接口、字段和方法的符号引用,以及字符串字面量和数值常量。这些信息在编译时被创建,并在运行时被Java虚拟机(JVM)使用。

在Java类文件中,是一个索引表,它从索引值1开始计数,每个条目都有一个唯一的索引。

  • 常量池计数器:在常量池之前,类文件有一个16位的常量池计数器,表示常量池中有多少项。它的值比实际常量数大1(因为索引从1开始)。
  • 常量池条目:每个常量池条目的开始是一个标签(1个字节),表明了常量的类型(如Class、Fieldref、Methodref等)。根据这个类型,后面跟着的数据结构也不同。

常量池相当于一个资源仓库,主要存放量大类型常量:

  • 字面量(Literals):字面量是不变的数据,主要包括数值(如整数、浮点数)和字符串字面量。例如,一个整数100或一个字符串"Hello World",在源代码中直接赋值,编译后存储在常量池中。
  • 符号引用(Symbolic References):符号引用是对类、接口、字段、方法等的引用,它们不是由字面量值给出的,而是通过符号名称(如类名、方法名)和其他额外信息(如类型、签名)来表示。这些引用在类文件中以一种抽象的方式存在,它们在类加载时被虚拟机解析为具体的内存地址。
public class ConstantTest {
    public final boolean bool = true;
    public final char aChar = 'a';
    public final byte b = 66;
    public final short s = 67;
    public final int i = 68;
    public final long ong = Long.MAX_VALUE;
    public final String str = "hello";
}
  • Java 定义了 boolean、byte、short、char 和 int 等基本数据类型,它们在常量池中都会被当做 int 来处理。
  1. 第一个字节 0x03 表示常量的类型为 CONSTANT_Integer_info
常量类型 标识符 描述符
CONSTANT_Integer_info 0x03 int 类型字面量
CONSTANT_Float_info 0x04 float 类型字面量
CONSTANT_Long_info 0x05 long 类型字面量
CONSTANT_Double_info 0x06 double 类型字面量

常量类型 标识符 描述符
CONSTANT_MethodHandle_info 0x0f 方法句柄
CONSTANT_MethodType_info 0x10 方法类型
CONSTANT_InvokeDynamic_info 0x12 动态调用点
CONSTANT_Fieldref_info 0x09 字段
CONSTANT_Methodref_info 0x0a 普通方法
CONSTANT_InterfaceMethodref_info 0x0b 接口方法
CONSTANT_Class_info 0x07 类或接口的全限定名
CONSTANT_String_info 0x08 字符串字面量
CONSTANT_Uft8_info 0x01 字符串
  1. 以 0x05 开头表示常量的类型为 CONSTANT_Long_info,Long.MAX_VALUE十六进制就是0x7FFFFFFF

  1. 以 0x01 开头表示 CONSTANT_Utf8_info,后两个字节0x0005表示数组长度为5,存储了字符串真正的值

  1. 以 0x08 开头表示 CONSTANT_String_info,表示字符串对象的引用,仅仅包含了一个指向常量池中 CONSTANT_Uft8_info 的索引,0x0034为索引,十进制是52, 通过索引 52 来找到 CONSTANT_Uft8_info。

  1. CONSTANT_Class_info,用来表示类和接口,和 CONSTANT_String_info 类似,第一个字节是标识,值为 0x07,后面两个字节是常量池索引,指向 CONSTANT_Utf8_info——字符串存储的是类或者接口的全路径限定名。索引为 13 的 CONSTANT_Class_info 指向的是是索引为 54 的 CONSTANT_Uft8_info,值为test/JVM/ConstantTest,十六进制是746573742f4a564d2f436f6e7374616e7454657374

  • 52的十六进制为0x36,CONSTANT_Class_info标识为0x07,就可以查找0x070036找到 CONSTANT_Class_info 在 class 文件中的位置了。

  1. CONSTANT_NameAndType_info,用来标识字段或方法,标识符为 12,对应的十六进制是 0x0c。后面还有 4 个字节,前两个是字段或者方法的索引,后两个是字段或方法的描述符,也就是字段或者方法的类型
class Dog {
    public void bark(int times, String name) {
    }
}
  • 用 jclasslib 可以看到 CONSTANT_NameAndType_info 包含的索引有两个

  • 在class文件中位置如下

  1. CONSTANT_MethodType_info,用来标识字段或方法,标识符为 0x0a。后面还有 4 个字节,前两个是CONSTANT_Class_info 的常量池索引,后两个是CONSTANT_NameAndType_info 的常量池索引

访问标记


  • 紧跟着常量池之后的区域就是访问标记(Access flags),这个标记用于识别类或接口的访问信息。总共有 16 个标记位可供使用,但常用的只有其中 7 个。左边是低位,右边是高位

  • 枚举,访问标记的信息为 0x4031 [public final enum]0x4031的二进制为0100 0000 0011 0001B
public enum Color {
    RED,GREEN,BLUE;
}

类索引、父类索引和接口索引


  • 这三部分用来确定类的继承关系
class Animal{}

interface Fly{}

class Bird extends Animal implements Fly{}

  • this_class 指向常量池中索引为 2 的 CONSTANT_Class_info。
  • super_class 指向常量池中索引为 3 的 CONSTANT_Class_info。
  • 有一个接口,所以 interfaces 的信息为1。

字段表


  • 一个类中定义的字段会被存储在字段表(fields)中,包括静态的和非静态的
public class Test {
    private String name;
}

  • field由三部分组成,按顺序分别是:

      1. 字段的访问标记:比如说是不是 public | private | protected,是不是 static,是不是 final 等。此例中为0x0002
      1. 字段名的索引:指向常量池中的 CONSTANT_Utf8_info。此例中为0x0004
      1. 字段的描述类型索引:指向常量池中的 CONSTANT_Utf8_info。此例中为0x0005
  • 表示方式

    • 对于基本数据类型来说,使用一个字符来表示,比如说 I 对应的是 int,B 对应的是 byte。
    • 对于引用数据类型来说,使用 L***; 的方式来表示,L 开头,; 结束,比如字符串类型为 Ljava/lang/String;
    • 对于数组来说,会用一个前置的 [ 来表示,比如说字符串数组为 [Ljava/lang/String;

方法表


  • 方法表和字段表类似,区别是用来存储方法的信息,包括方法名,方法的参数,方法的签名
public class Test {
    public static void main(String[] args) {
    }
}

  • 访问标记是 public static 的。此例中为0x0009
  • 方法名为 main。指向常量池中的 CONSTANT_Utf8_info。此例中为0x000B
  • 方法的参数为字符串数组;返回类型为 Void。指向常量池中的 CONSTANT_Utf8_info。此例中为0x000C

属性表


  • 属性表是 class 文件中的最后一部分,通常出现在字段和方法中。
public class Test {
    public static final int DEFAULT_SIZE = 128;
}
  • ConstantValue,用来表示静态变量的初始值

  • 属性名索引指向常量池中值为“ConstantValue”的常量。
  • 属性长度的值为固定的 2,因为索引只占两个字节的大小。
  • 常量值索引指向常量池中具体的常量,如果常量类型为 int,指向的就是 CONSTANT_Integer_info。

标签:info,文件,CONSTANT,常量,class,索引,JVM,public,结构
From: https://www.cnblogs.com/sprinining/p/18303183

相关文章

  • 精准搜索:本地文件检索工具的高效策略
    背景背景1:在日常的工作中,本地磁盘随着工作时间的变长,新建的目录会越来越多存放的文件也越来越多;每次想要找一个文件,确实要浪费一点时间,本着让时间更高效的原则,想着如果借助程序去检索那是不是更快些,于是有了下边的实践。背景2:保险的销售人员也就是业务老师,由于资料过多,找起来确......
  • C文件操作
    1.为什么使用文件我们前面学习结构体时,写通讯录的程序,当通讯录运行起来的时候,可以给通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯录程序的时候,数据又得重新录入,如果使用这样的通讯录就很难受。我们在想既然......
  • 【JVM_01】——初识JVM运行流程
    目录1-引言:初识JVM1-1JVM是什么?(What)1-1-1概念1-1-2优点1-2为什么学习JVM?(Why)2-核心:JVM工作的原理(How)⭐2-1JVM的组成部分及工作流程2-2学习侧重点3-小结(知识点大纲):3-1JVM组成3-2类加载器3-3垃圾回收3-4JVM实践1-引言:初识JVM1-1JVM是什么?(......
  • 在 package.json 文件中,版本号前的 ^ 符号含义
    在package.json文件中,版本号前的^符号表示兼容某个主版本(majorversion)的更新。具体来说,^符号允许自动安装具有相同主版本号的更新版本,但不包括主版本号变更的版本。例如:***"^1.2.3"允许的版本范围是>=1.2.3<2.0.0。这意味着会自动安装1.2.4、1.3.0等版本,但不会安装......
  • 认识JVM
    类加载器运行时数据区执行引擎执行引擎的任务就是将字节码指令解释/编译为对应平台上的本地机器指令JVM架构图......
  • logging模块切割日志时:另一个程序正在使用此文件,进程无法访问。
    使用:  concurrent-log-handlerGITHUB:  https://github.com/Preston-Landers/concurrent-log-handler安装: pipinstallconcurrent-log-handlerimportloggingfromconcurrent_log_handlerimportConcurrentRotatingFileHandlerlogger=logging.getLogger(__name_......
  • 【数据结构】线性结构——数组、链表、栈和队列
    目录前言一、数组(Array)1.1优点1.2缺点1.3适用场景二、链表(LinkedList)2.1优点2.2缺点2.3适用场景三、栈(Stack)3.1优点3.2缺点3.3适用场景四、队列(Queue)4.1优点4.2缺点4.3适用场景......
  • springboot使用logback日志出现LOG_PATH_IS_UNDEFINED文件夹的问题
    logback现在基本上已经成为springboot日志框架中使用最多的日志实现,在使用中与各中间件集成的一些注意事项记录如下 一SpringBoot中logback读取application.properties(application.yml)中的属性其中使用的时候发现了一个问题,就是如果使用的lobback配置文件的名称是logb......
  • 数据结构第28节 字典树
    字典树(Trie,也称前缀树)是一种用于存储字符串的树形数据结构。它将字符串中的字符作为树的边,每个节点代表一个可能的前缀。字典树非常适合处理大量字符串的搜索、插入和删除操作,尤其是在查找具有相同前缀的字符串时非常高效。基本概念:根节点:通常不包含任何数据,它的子节点包......
  • 【原创软件】第7期:文件夹生成器V1.0-按照列表批量生成文件夹,简单小巧
    一、背景因为工作需要,需要批量创建文件夹。为了省去人工创建时间,使用aardio制作了一个软件。  二、功能演示  三、下载地址 https://www.123pan.com/s/9Rn9-1xppH.html  四、源代码 源代码分享:importwin.ui;importfsys;importfsys.dlgimportproce......