深入理解Java虚拟机笔记---class类文件魔数,版本,常量池

魔数

每个class文件的头4个字节称为魔数(Magic Number),其值为:0xCAFEBASE,它的唯一作用是用于确定这个文件是否为一个能被虚拟机接受的class文件。使用魔数而不是扩展名来进行识别主要是基于安全的考虑,因为文件的扩展名可以随意地被改动。

版本号

紧接着魔的4个字节存储的是class文件的版本号:第5和第6个字节是次版本号(Minor Version),第7和第8个字节是主版本号(Major Version)。java的版本是从45开始的,JDK1.1之后的每个JDK大版本发布主版本号上加1(JDK1.0-1.1使用了45.0-45.3的版本号),高版本的JDK能向下兼容以前版本的class文件,但不能运行以后版本的class文件,即使文件格式并未发生变化。JDK1.2对应主版本号为46,JDK1.3为47,依此类推。

常量池

紧接着主次版本号之后的是常量池入口,常量池是class文件结构中与其它项目关联最多的数据类型,也是占用class文件空间最大的数据项目之一,同时它还是class文件中第一个出现的表类型数据项目。

由于常量池中常量的数据是不固定的,所以在常量池的入口需要放置一荐u2类型的数据,代表常量池容量计算值(constant_pool_count)。与Java语言习惯不一样的是,这个容量计数是从1而不是0开始的。将第0项常量出来的目的是为了满足后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的意思。class文件结构中只有常量池的容量计数是从1开始,对于其它集合类型,包括接口索引集合,字段表集合,方法表集合的容量计算都是从0开始的。

常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。字面量比较接近于Java语言层面的常量概念,如文本字符串,被声明为final的常量值等。而符号引用则属性编译原理方面的概念,包含了下面三类常量:

a.类和接口的全限定名(Fully Qualified Name)

b.字段的名称和描述符(Descriptor)

c.方法的名称和描述符

常量池中的每一项常量都是一个表,共有11种结构各不相同的表结构数据,这11种表都有一个共同的特点,就是表开始的第一位是一个u1类型的标志位,代表当前这个常量属性哪种常量类型,11种常量类型具体含义如下:

各常量项结构:

时间: 2024-10-08 22:36:37

深入理解Java虚拟机笔记---class类文件魔数,版本,常量池的相关文章

深入理解Java虚拟机笔记---class类文件结构概述

class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格紧凑地排列在class文件中,中间没有任何分隔符.当遇到需要占用8位字节以上的的数据项时,则会按照高位在前的方式侵害成若干个8位字节进行存储. 根据Java虚拟机规范的规定,class文件格式采用一种类似于C语言结构体的伪结构来存储,这种伪结构只有两种数据类型:无符号数和表.无符号数属于基于数据类型,以u1.u2.u4.u8来分别代码1个字节.2个字节.4个字节.8个字节的无符号数,无符号数可以用于描述数字.索引引用.数量值,或

《深入理解java虚拟机》:类的初始化

深入理解java虚拟机>:类的初始化 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.其中验证.准备.解析3个部分统称为连接.类加载的过程包括了加载.验证.准备.解析.初始化五个阶段. 加载.验证.准备.初始化和卸载这5个阶段的顺序时确定的,类的加载过程必须按照这种顺序按部就班的开始,而解析阶段则不一定,它在某些情况下可以在初始化阶段之后开始,这是为了支持Java语言的运行时绑定(也成为动态绑定或晚期绑定).另外注意这里的

深入理解java虚拟机笔记(一)-java内存区域与内存溢出

1. 前言 这是深入理解java虚拟机一书的笔记,来自第二章.因为这本书讲的比较深奥,这是第二次看,需要记录一下笔记. 2. 运行时数据区域 java虚拟机所管理的内存分为以下几个区域. ps:图片来自网络 2.1 程序计数器 程序计数器是一块较小的内存空间,他可以看做是当前线程所执行字节码的行号指示器.字节码解释器工作时就是通过改变这个计数器的值来选去下一条要执行的字节码指令,分之.循环.跳转.异常处理.线程恢复等基础功能都需要依赖这个计数器来完成. 这块内存是线程私有的内存. 如果线程在执行

深入理解Java虚拟机笔记---属性表集合

在Class文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息.与Class文件中其它的数据项目要求的顺序.长度和内容不同,属性表集合的限制稍微宽松一些,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写入自己定义的属性信息,Java虚拟机运行时会忽略掉它不认识的属性.为了能正确地解析Class文件,<Java虚拟机规范(第二版)>中预定义了9荐虚拟机实现应当能识别的属性,具体如下表所示: 对于每个属性,它的名称需要

深入理解Java虚拟机笔记---方法调用

方法调用并不等同于方法执行,方法调用阶段唯一的任务就是确定调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程.在程序运行时,进行方法调用是最普遍.最频繁的操作.在Class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在Class文件里存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址(相当于直接引用).这个特性给Java带来了更强大的动态扩展能力,但也使得Java方法的调用过程变得相对复杂,需要在类加载期间甚至到运行期间才能确定目标方法的直接引用.

深入理解Java虚拟机笔记---类加载过程

一.加载 "加载"(Loading)阶段是"类加载"(Class Loading)过程的一个阶段.在加载阶段,虚拟机需要完成以下三件事情: a.通过一个类的全限制名来获取定义此类的二进制字节流. b.将这个字节流所代表的静态存储结构转化为方法区的运行进数据结构. c.在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口. 虚拟机规范的这三点要求实际上并不具体,因此虚拟机实现与具体应用的灵活度相当大.例如"通过一

深入理解Java虚拟机笔记---类加载时机

类从被加载到虚拟机内存中开始,到缷载出内存为止,它的整个生命周期包括了:加载(Loading),验证(Verification),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using),缷载(Unloading)七个阶段.其中验证,准备,解析三个阶段统称为连接(Linking)阶段,这七个阶段的发生顺序如下图: 加载,验证,准备,初始化和缷载这五个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:

深入理解Java虚拟机--笔记1

Java内存区域与内存溢出异常 运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域. 1 程序计数器--Program Counter Register 一块较小的内存空间,作用可视为当前线程所执行的字节码的行号指示器,没个线程有自己独立的程序计数器,即"线程私有"的内存区域. 若线程当前执行的是一个Java方法,则这个计数器记录的是当前执行的虚拟机字节码指令的地址: 若线程当前执行的是一个Native方法,则这个计数器值为空(Un

深入理解Java虚拟机笔记---内存区域

Java虚拟机在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域有自各的用途,以及创建及销毁时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁.根据<Java虚拟机规范(第2版)>规定,Java虚拟机管理的内存区域包括以下几个运行时数据区域,下如图 1.程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过