本文将从宏观和微观的角度介绍类文件结构,虚拟机的加载类文件机制,类文件生命周期和字节码加载引擎,并将加深对它的理解。虚拟机的工作。
问题
如何将JAVA文本文件翻译成CLASS二进制文件?
如何理解CLASS文件的组成?
虚拟机如何加载类文件使用的生命周期?
如何使用该系列虚拟机的诊断工具?
消除虚拟机内存的机制?
虚拟机架构指令集?
2.关键词
编译,幻数,常量组,文字,数据表,堆栈,方法区,程序计数器,内存引用,内存溢出,垃圾收集器,新区域,永久区域,指令集
3.全文摘要。
本文将从宏观和微观的角度介绍类文件结构,虚拟机的加载类文件机制,类文件生命周期和字节码加载引擎,并将加深对它的理解。虚拟机的工作。
文件结构分析4.CLASS
从我们学习JAVA语言的第一天起,我们就执行了JAVA/JAVAC命令。 JAVAC正在使用后缀.java将我们编写的文本文件编译为带有.class后缀的字节码文件。在上一章中,我们在介绍代码的本质时,了解了JAVA语言的语法元素。可以使用文本编辑器打开Java文件,该编辑器也熟悉java代码,符合java语言语法。但对于课堂内容,我们必须更加陌生。在上一章中,我们知道编译器将代码转换为机器指令。类文件是否也是Java虚拟机翻译的指令?
实际上,当java文件被编译成类文件时,它与java语言无关。指令执行引擎是JVM虚拟机。其他编程语言(如Scala,Python等)可以编译为类文件,然后放在JVM中执行。这样,我们需要探索类文件的本质。
4.1 CLASS文件的示例
首先,我们从微观的角度介绍类文件的结构。首先编写一个简单的java文本文件,然后将其编译成一个类文件来观察该类的结构。
首先定义一个接口文件,Add.java文件如下:
包com.lzh.jvm;
公共接口添加{
Int add(int i,int j);
}
然后为AddImpl.java接口编写一个实现类,它基本上包含我们经常使用的文件结构:
包com.lzh.jvm;公共类实现AddImpl添加{
public static end int TOP=100;
私人连锁点;
Public int add(int i,int j){
返回i + j;
}
}
既然有定义的包名,你必须创建一个文件目录COM/LZH/JVM,然后编译COM/LZH/JVM/Add.java文件和COM/LZH/JVM/AddImpl.java文件目录电流。我得到了Add.class文件和AddImpl.class文件。
二进制add.java:
程序员从宏观和微观的角度分析JVM虚拟机!
二进制add.class:
程序员从宏观和微观的角度分析JVM虚拟机!
二进制AddImpl.java:
程序员从宏观和微观的角度分析JVM虚拟机!
二进制AddImpl.class:
程序员从宏观和微观的角度分析JVM虚拟机!
使用WinHex二进制编辑工具打开前面的四个图像。左边是二进制代码文件,而右侧是标准的ASCII代码,因此它只能代表在英文键盘字符。如果中文出现,它将显示令人困惑的字符。为了便于阅读,该工具将显示与表示一个字节(8位)的空间中的两个十六进制代码十六进制格式。
直觉上,我们可以看到java文件占用的存储空间少于类,这也与前一章介绍的代码转换过程一致。实质上,计算机不知道java文件的内容。 Java是一种高级语言。语法更接近人类语言,但很难理解计算机。因此,您必须将java文件的内容转换为jvm可识别的文件格式。
高级语言的高度抽象语言元素和机器指令的翻译需要更多的“说话语言”来指导计算机逐步执行代码。在下一节中,我们将解释类文件的结构,以了解jvm如何理解执行类的内容。
4.2类文件结构的描述
在本节中,我们通过将AddImpl.class添加到上一个示例来介绍类的结构。从结构的角度来看,类文件只存储两种类型的数据,即基本字段和表。
基本字段:用于描述数字,引用,值或字符串的无符号数字。类型为u1,u2,u4,u8表示占用的字节数。
表:只有一行变量列的表结构,每个字段可以是基础字段或另一个表的索引4.2.1幻数
用于确定文件类型,我们通常使用文件的后缀来确定文件类型,但如果修改后缀,则会出现安全问题。该类以4个字节的空格开头以指示类的类型,CA FE BA BE表示类类型文件。
4.2.2版本
幻数后跟4个字节以指示jdk版本号。
次版本号:前两个字段0x0000
主版本号:最后两个字段为0x0035,转换小数为53,对应jdk1.9
4.2.3恒定池
顾名思义,常量分组用于存储字符串常量。链常数包含:
文字:绳索,不变
引用设置为:类/接口的全名,字段/方法的名称和修饰符
我们知道该类本质上是表的集合。除了存储在常量池中的表具有特定类型之外,相同的常量池也不例外。共有11种类型,如下表所示(图像参考《深入理解Java虚拟机 JVM高级特性与最佳实践》):
程序员从宏观和微观的角度分析JVM虚拟机!
每个表中表格的结构如下所述:
程序员从宏观和微观的角度分析JVM虚拟机!
11种类型表的第一个字段统一为标记字段标签,占用字节u1,用于指示存储在表中的数据类型。
从常量集开始处开始的前两个字节(u2)表示常量集的长度,即表的数量。
我们可以看到示例中常量组的数量是0x0017,并且到十进制的转换是23.由于表0是保留索引,这意味着没有链被引用,因此表的索引real是从1计算出来的,即1~23共22个表。
首先,我们观察一组常量AddImpl.class并分析第一个表的表结构。找到表地看到,U1位置后立即表的数量为0A,转换为十进制10,该表型是CONSTANT_Methodref_info,表结构观察知道以下两个位置U2属于表的字段,两个字段都是表索引的类型,0x0003表示引用了第三个表,0x0013表示引用了表19。
然后,将表与所述第二表的所述第一表结束时,表标签是CONSTANT_Class_info 07的类型是,所述第二空间是U2,字段值是0x0014和标号20表制成。
然后,分析第三个表,按照相同的方法,可以随时分析常量集的表的结构。常量分组的功能是将源代码的所有文本数据集中在常量分组的区间中。表中的表彼此引用以管理文本数据。因为表之间的参考,最新的文本数据被存储在CONSTANT_Class_info表,并且该表指定字段长度的文本长度是类型U2,它占据2个字节,16功率的空间2, 65536/1024=64 K,因此变量java或方法名称的大小不能超过64K。4.2.4接入信号
修改后的类或接口的受限制标记
在常量分组结束后,2字节访问指示符立即共32个指示位。
4.2.5类索引/父/接口的集合
类索引,索引父类和接口索引集:所述CONSTANT_Class_info表指向常数集,然后在表指向CONSTANT_Class_info字面字节字段CONSTANT_Utf8_info特定表的索引。
4.5.6字段表的收集
字段表的集合:
字段表的结构如下
矩阵[表,表示该字段用来表示类中的所有变量(在该方法中不包括局部变量)
4.5.7方法表的收集
表的收集方法:
方法表的结构如下
4.5.8物业单的收集
物业单收集
该方法的主体内容被编译成Code属性,代码表的结构如下
代码,异常,LineNumberTable,LocalVariableTable,的SourceFile,ConstantValue,InnerClasses,过时的,合成
类文件就像是产品的模具。模具制造过程是加载类JVM存储器的过程,然后根据类的模具打印JVM对象。重点是模具的设计。事实上,模具是生产出来的,需要一个模具。这是该类严格的结构规范。类文件结构的规范提供了几个方面的要求。只有根据此要求制造的模具可用并且可用于制造产品,否则不能使用产品线。就像jvm判断该类不符合规范并拒绝加载一样。
5.类文件生命周期
班级加载机会
类初始化的时刻主要是被动初始化,并且在不使用时不会被初始化。
类加载过程