JVM-(2)Class File Format

Class File Format

       在上一篇JVM入门文章中,我们了解到 JVM 之所以是跨语言的平台,是因为 JVM 通过解释.class 文件执行程序,所以各种语言只要能依照class文件格式标准正确编译成 .class 文件就可以被 JVM 执行,本篇将简单介绍 .class 文件格式。

Class 文件概述

       Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地 排列在Class文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。当遇到需要占用8位字节以上空间的数据项 时,则会分割成若干个8位字节进行存储。

       根据Java虚拟机规范的规定,Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表,后面的解析都要以这两种数据类型为基础,所以这里要先介绍这两个概念。

       无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8 编码构成字符串值。

       表是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地 以“_info”结尾。表用于描述有层次关系的复合结构的数据,整个Class文件本质上就是一张表,它由表6-1所示的数据项构成。

(摘自深入理解Java虚拟机第2版

举例说明

以一个非常简单的 Java 类举例说明:

package com.hs.example.base;

public class HelloWorld {
}

编译后的 .class 文件以 十六进制 方式打开(以下使用的是 Sublime Text):

Magic Number (魔数)

Class文件的头4个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。上述Class文件中 cafe babe 就是魔数。
注意: 一个字节占8位,一个最大的十六进制的数 f 转换成二进制为 1111 占了4位,所以一个字节由2个十六进制数组成。

Minor Version(次版本号)

占用两个字节,上述 0000 代表Class文件次版本号,转换成十进制为 0

Major Version(主版本号)

0034 代表Class文件主版本号,转换成十进制数为 52 ,Class文件52.0版本号对应的 jdk 1.8

constant_pool_count(常量池容量计数值)

上述 0010 表示常量池计数值,转换成十进制为 16

constant_pool(常量池)

常量池可以理解为Class文件之中的资源仓库, 它是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时它还是在Class文件中第一个出现的表类型数据项目。

常量池容量计数是从1开始,设计者将第0项常量空出来是有特殊考虑的,这样做的目的在于满足后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池 项目”的含义,这种情况就可以把索引值置为0来表示。

常量池中每一项常量都是一个表,表开始的第一位是一个u1类型的标志位(tag,取值 见表6-3中标志列),代表当前这个常量属于哪种常量类型。

如:以上 0a 转换成 十进制为 10 ,对照常量池项目类型表格,对应的类型为 CONSTANT_Methodref_info。

常量池是最烦琐的数据,是因为这14种常量类型各自均有自己的结构,各常量项结构如下:



从表中得知 CONSTANT_Methodref_info 一共占了 5个字节 , 及 0a00 0300 0d 表示的是常量池中 #1 号位置的数据,0003 十进制为3 ,它指向 CONSTANT_Class_info 的3号位置, 00 0d 十进制为 13 ,它指向 CONSTANT_NameType 13 号位置
。。。。。。

使用插件

使用 IDEA 插件 jclasslib Bytecode Viewer 可以很方便地查看 .calss 文件信息

Java Runtime Environment (JRE) refers to the software environment that includes the Java Virtual Machine (JVM) and the necessary libraries for running Java applications. A class file is a compiled form of Java source code, containing bytecode, which can be executed by the JVM. The "class file version 61.0" you mentioned does not seem to correspond to an official version number in the standard Java specification. Java class files have version numbers based on the Java platform version they were designed to work with, following a format like `major.minor`. For example, version 61.0 might be a custom or non-standard build, or it could indicate a modified version with custom extensions. Java standard class file formats are defined up to version 55.0, corresponding to Java SE 8. Here's what you need to know about the standard class file formats: - **Java SE 5**: Class file version 49.0 - **Java SE 6**: Class file version 50.0 - **Java SE 7**: Class file version 51.0 - **Java SE 8**: Class file version 52.0 If your JRE is limited to recognizing class files up to version 55.0, it means it may not support newer features introduced in later Java versions, and any application with a higher class file version may encounter issues or require a more recent JRE for proper execution. Here are some related questions: 1. What are the main differences between Java versions regarding class file format changes? 2. Can you run Java SE 9 or later applications on a JRE with version 55.0? 3. How can one ensure compatibility between older and newer class files when deploying applications?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值