虚拟机Class文件结构笔记

简介:

1.Java语言的平台无关性

Java是与平台无关的语言,“一次编写,到处运行”,
这一方面依赖于Java源代码编译后生成的存储字节码的文件,即Class文件是语言和平台无关的;

另一方面依赖于Java虚拟机的实现。

Java虚拟机并不关心Class的来源是什么语言,只要它符合一定的结构,就可以在Java中运行。
Java语言中的各种变量、关键字和运算符的语义最终都是由多条字节码命令组合而成的,
因此字节码命令所能提供的语义描述能力肯定会比Java语言本身更强大,
这便为其他语言实现一些有别于Java的语言特性提供了基础,而且这也正是在类加载时要进行安全验证的原因。

2.Class类文件结构

class文件是一种8位字节的二进制流文件, 各个数据项按顺序紧密的从前向后排列, 相邻的项之间没有间隙, 这样可以使得class文件非常紧凑, 体积轻巧, 可以被JVM快速的加载至内存, 并且占据较少的内存空间。
我们的Java源文件, 在被编译之后, 每个类(或者接口)都单独占据一个class文件, 并且类中的所有信息都会在class文件中有相应的描述, 由于class文件很灵活, 它甚至比Java源文件有着更强的描述能力。

class文件中存在以下数据项:

 

 

类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attribute_count 1
attribute_info attributes attributes_count

 无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会在其前面使用一个前置的容量计数器来记录其数量,而便跟着若干个连续的数据项,称这一系列连续的某一类型的数据为某一类型的集合,如:fields_count个field_info表数据便组成了方法表集合。

(1)魔数和版本号 magic minor_version&major_version
每个Class文件的头4个字节称为魔数(magic),它的唯一作用是判断该文件是否为一个能被虚拟机接受的Class文件。它的值固定为0xCAFEBABE。
紧接着magic的4个字节存储的是Class文件的次版本号和主版本号,一般情况下, 高版本的JVM能识别低版本的javac编译器编译的class文件, 而低版本的JVM不能识别高版本的javac编译器编译的class文件。 如果使用低版本的JVM执行高版本的class文件, JVM会抛出java.lang.UnsupportedClassVersionError 。

(2)常量池计数和常量池 constant_pool_count&constant_pool
常量池是class文件中的一项非常重要的数据。 常量池中存放了文字字符串, 常量值, 当前类的类名, 字段名, 方法名, 各个字段和方法的描述符, 对当前类的字段和方法的引用信息, 当前类中对其他类的引用信息等等。
常量池中主要存放两大类常量:字面量和符号引用。字面量比较接近于Java层面的常量概念,如文本字符串、被声明为final的常量值等。而符号引用总结起来则包括了下面三类常量:

类和接口的全限定名(即带有包名的Class名)
字段的名称和描述符(private、static等描述符)
方法的名称和描述符(private、static等描述符)

(3) 访问标志 access_flag

在常量池结束之后,紧接着的2个字节代表访问标志(access_flag),这个标志用于识别一些类或接口层次的访问信息,包括:这个Class是类还是接口,是否定义为public类型,abstract类型,如果是类的话,是否声明为final,等等。每种访问信息都由一个十六进制的标志值表示,如果同时具有多种访问信息,则得到的标志值为这几种访问信息的标志值的逻辑或。

(4) 类索引和父类索引 接口索引集合 this_class、super_class、interfaces
类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而接口索引集合(interfaces)则是一组u2类型的数据集合,Class文件中由这三项数据来确定这个类的继承关系。类索引、父类索引和接口索引集合都按照顺序排列在访问标志之后,类索引和父类索引两个u2类型的索引值表示,它们各自指向一个类型为COMNSTANT_Class_info的类描述符常量,通过该常量中的索引值找到定义在COMNSTANT_Utf8_info类型的常量中的全限定名字符串。而接口索引集合就用来描述这个类实现了哪些接口,这些被实现的接口将按implements语句(如果这个类本身是个接口,则应当是extend语句)后的接口顺序从左到右排列在接口的索引集合中。

(5)字段表 fields
字段表(field_info)用于描述接口或类中声明的变量。字段包括了类级变量或实例级变量,但不包括在方法内声明的变量。字段的名字、数据类型、修饰符等都是无法固定的,只能引用常量池中的常量来描述。

(6)方法表 methods
方法表(method_info)的结构与属性表的结构相同,方法里的Java代码,经过编译器编译成字节码指令后,存放在方法属性表集合中一个名为“Code”的属性里。
与字段表集合相对应,如果父类方法在子类中没有被覆写,方法表集合中就不会出现来自父类的方法信息。但同样,有可能会出现由编译器自动添加的方法,最典型的便是类构造器“<clinit>”方法和实例构造器“<init>”方法。
在Java语言中,要重载一个方法,除了要与原方法具有相同的简单名称外,还要求必须拥有一个与原方法不同的特征签名,特征签名就是一个方法中各个参数在常量池中的字段符号引用的集合,也就是因为返回值不会包含在特征签名之中,因此Java语言里无法仅仅依靠返回值的不同来对一个已有方法进行重载。

(7)属性表 attributes
属性表(attribute_info)在前面已经出现过多系,在Class文件、字段表、方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。

3.final、static、static final修饰的字段赋值的区别

static修饰的字段在类加载过程中的准备阶段被初始化为0或null等默认值,而后在初始化阶段(触发类构造器<clinit>)才会被赋予代码中设定的值,如果没有设定值,那么它的值就为默认值。
final修饰的字段在运行时被初始化(可以直接赋值,也可以在实例构造器中赋值),一旦赋值便不可更改;
static final修饰的字段在Javac时生成ConstantValue属性,在类加载的准备阶段根据ConstantValue的值为该字段赋值,它没有默认值,必须显式地赋值,否则Javac时会报错。可以理解为在编译期即把结果放入了常量池中。

 


本文转自邴越博客园博客,原文链接:http://www.cnblogs.com/binyue/p/4560484.html,如需转载请自行联系原作者

相关文章
|
1月前
|
数据库 虚拟化 Windows
虚拟机数据恢复—XenServer虚拟机磁盘文件丢失的数据恢复案例
虚拟机数据恢复环境: 某品牌服务器通过同品牌某型号的RAID卡,将4块STAT硬盘为一组RAID10阵列。上层部署XenServer虚拟化平台,虚拟机安装Windows Server系统,每台虚拟机有两个虚拟机磁盘(系统盘 + 数据盘),虚拟机作为Web服务器使用。 虚拟机故障&分析: 机房异常断电导致服务器中一台VPS(XenServer虚拟机)不可用,虚拟磁盘文件丢失。
|
29天前
|
存储 运维 虚拟化
虚拟化数据恢复——Hyper-V虚拟化故障导致虚拟机文件丢失的数据恢复案例
在Windows Server上部署的Hyper-V虚拟化环境中,因存储中虚拟机数据文件丢失导致服务瘫痪。北亚企安数据恢复工程师通过物理检测、操作系统及文件系统检测,确定为人为格式化造成,并通过镜像硬盘、重组RAID、分析并恢复文件索引项等步骤,成功恢复数据,最终在新Hyper-V环境中验证并迁移所有虚拟机,确保用户业务恢复正常运行。
|
4月前
|
存储 算法 安全
Java面试题:Java内存模型及相关知识点深度解析,Java虚拟机的内存结构及各部分作用,详解Java的垃圾回收机制,谈谈你对Java内存溢出(OutOfMemoryError)的理解?
Java面试题:Java内存模型及相关知识点深度解析,Java虚拟机的内存结构及各部分作用,详解Java的垃圾回收机制,谈谈你对Java内存溢出(OutOfMemoryError)的理解?
70 0
|
1月前
|
Linux 测试技术 虚拟化
解决虚拟机文件因快照占用硬盘空间较多的情况(压缩虚拟机文件,节省硬盘空间)
解决虚拟机文件因快照占用硬盘空间较多的情况(压缩虚拟机文件,节省硬盘空间)
134 1
|
2月前
|
存储 SQL 数据挖掘
虚拟化数据恢复—VMware虚拟机vmdk文件被误删除的数据恢复案例
虚拟化数据恢复环境: 某品牌服务器(部署VMware EXSI虚拟机)+同品牌存储(存放虚拟机文件)。 虚拟化故障: 意外断电导致服务器上某台虚拟机无法正常启动。查看虚拟机配置文件发现这台故障虚拟机除了磁盘文件以外其他配置文件全部丢失,xxx-flat.vmdk磁盘文件和xxx-000001-delta.vmdk快照文件还在。管理员联系VMware工程师寻求帮助。VMware工程师尝试新建一个虚拟机来解决故障,但发现ESXi存储空间不足。于是将故障虚拟机下的xxx-flat.vmdk磁盘文件删除,然后重建一个虚拟机并且分配固定大小的虚拟磁盘。
|
1月前
|
Kubernetes Linux 容器
解决删除快照后启动虚拟机显示指定的文件不是虚拟磁盘 打不开磁盘“路径”或它所依赖的某个快照磁盘。 模块“disk”启动失败。 未能启动虚拟
解决删除快照后启动虚拟机显示指定的文件不是虚拟磁盘 打不开磁盘“路径”或它所依赖的某个快照磁盘。 模块“disk”启动失败。 未能启动虚拟
135 0
|
4月前
|
SQL 存储 数据库
虚拟化数据恢复—XenServer虚拟机磁盘文件丢失的数据恢复案例
虚拟化数据恢复环境: 某品牌R720服务器,4块STAT硬盘通过H710P阵列卡组建了一组raid10磁盘阵列。服务器上部署XenServer虚拟化平台,虚拟机安装Windows Server系统,作为Web服务器使用,运行SQL Server数据库。共有2个虚拟磁盘:数据盘+系统盘。 虚拟化故障: 机房断电导致XenServer虚拟化平台中一台VPS不可用,XenServer虚拟机磁盘文件丢失。
虚拟化数据恢复—XenServer虚拟机磁盘文件丢失的数据恢复案例
|
5月前
|
存储 安全 Java
深入理解Java内存模型(JMM)与虚拟机的内存结构(JVM)
深入理解Java内存模型(JMM)与虚拟机的内存结构(JVM)
|
10天前
|
存储 SQL 数据库
虚拟化数据恢复—Vmware虚拟机误还原快照的数据恢复案例
虚拟化数据恢复环境: 一台虚拟机从物理机迁移到ESXI虚拟化平台,迁移完成后做了一个快照。虚拟机上运行了一个SQL Server数据库,记录了数年的数据。 ESXI虚拟化平台上有数十台虚拟机,EXSI虚拟化平台连接了一台EVA存储,所有的虚拟机都存放在EVA存储上。 虚拟化故障: 工组人员误操作将数年前迁移完成后做的快照还原了,也就意味着虚拟机状态还原到数年前,近几年数据都被删除了。 还原快照相当于删除数据,意味着部分存储空间会被释放。为了不让这部分释放的空间被重用,需要将连接到这台存储的所有虚拟机都关掉,需要将不能长时间宕机的虚拟机迁移到别的EXSI虚拟化平台上。
88 50
|
1月前
|
安全 虚拟化 数据中心
Xshell 连接 VMware虚拟机操作 截图和使用
Xshell 连接 VMware虚拟机操作 截图和使用
49 4