├── 1-Introduction ├── 1.1_A_Bit_of_History.md ├── 1.2_The_Java_Virtual_Machine.md ├── 1.3_Organization_of_the_Specification.md ├── 1.4_Notation.md └── 1.5_Feedback.md ├── 2-The_Structure_of_The_Java_Virtual_Machine ├── 2.1_The_class_File_Format.md ├── 2.2_Data_Types.md ├── 2.3_Primitive_Types_and_Values │ ├── 2.3.1_Integral_Types_and_Values.md │ ├── 2.3.2_Floating-Point_Types_Value_Sets_and_Values.md │ ├── 2.3.3_The_returenAddress_Type_and_Values.md │ ├── 2.3.4_The_boolean_Type.md │ └── Primitive_Types_and_Values.md ├── 2.4_Reference_Types_and_Values.md ├── 2.5_Run-Time_Data_Areas │ ├── 2.5.1_The_pc_Register.md │ ├── 2.5.2_Java_Virtual_Machine_Stacks.md │ ├── 2.5.3_Heap.md │ ├── 2.5.4_Method_Area.md │ ├── 2.5.5_Run-time_Constant_Pool.md │ ├── 2.5.6_Native_Method_Stacks.md │ └── Run-Time_Data_Areas.md ├── 2.6_Frames │ ├── 2.6.1_Local_Variables.md │ ├── 2.6.2_Operand_Stacks.md │ ├── 2.6.3_Dynamic_Linking.md │ ├── 2.6.4_Normal_Method_Invocation_Completion.md │ ├── 2.6.5_Abrupt_Method_Invocation_Completion.md │ └── Frames.md ├── 2.7_Representation_of_Objects.md ├── 2.8_Floating_Point_Arithmetic │ ├── 2.8.1_Java_Virtual_Machine_Floating_Point_Arithmetic_and_IEEE_754.md │ └── Floating_Point_Arithmetic.md └── The_Structure_of_the_Java_Virtual_Machine.md ├── 4-The_class_File_Format ├── 4.1_The_ClassFile_Structure.md ├── 4.2_Names │ ├── 4.2.1_Binary_Class_and_Interface_Names.md │ ├── 4.2.2_Unqualified_Names.md │ └── 4.2.3_Module_and_Package_Names.md ├── 4.3_Descriptors │ ├── 4.3.1_Grammar_Notation.md │ ├── 4.3.2_Field_Descriptors.md │ ├── 4.3.3_Method_Descriptors.md │ └── Descriptors.md ├── 4.4_The_Constant_Pool │ ├── 4.4.1_The_CONSTANT_Class_info_Structure.md │ ├── 4.4.2_The_CONSTANT_Fieldref_info_CONSTANT_Methodref_info_and_CONSTANT_InterfaceMethodref_info_Structures.md │ ├── 4.4.3_The_CONSTANT_String_info_Structure.md │ ├── 4.4.4_The_CONSTANT_Integer_info_and_CONSTANT_Float_info_Stuctures.md │ └── The_Constant_Pool.md └── The_class_File_Format.md ├── 5-Loading_Linking_and_Initializing ├── 5.1_The_Run-Time_Constant_Pool.md ├── 5.2_Java_Virtual_Machine_Startup.md ├── 5.3_Creation_and_Loading │ ├── 5.3.1_LoadingUsing_the_Bootstrap_class_Loader.md │ ├── 5.3.2_Loading_Using_a_User_defined_Class_loader.md │ ├── 5.3.3_Creating_Array_Classes.md │ ├── 5.3.4_Loading_Constraints.md │ ├── 5.3.5_Deriving_a_Class_from_a_class_File_Representation.md │ └── Creation_and_Loading.md ├── 5.4_Linking │ └── Linking.md └── Loading_Linking_and_Initializing.md ├── 6-The_Java_Virtual_Machine_Instruction_Set ├── 6.1_Assumptions_The_Meaning_of_Must.md ├── 6.2_Reserved_Opcodes.md ├── 6.3_Virtual_Machine_Errors.md ├── 6.4_Format_of_Instruction_Descriptions.md ├── 6.5_Instructions │ ├── aaload.md │ ├── aastore.md │ └── aconst_null.md └── The_Java_Virtual_Machine_Instruction_Set.md ├── LICENSE └── README.md /1-Introduction/1.1_A_Bit_of_History.md: -------------------------------------------------------------------------------- 1 | Java是一个通用的,并发,面向对象的语言。他的语法与C/C++类似,但是,它忽略了许多C/C++中复杂,扑所迷离和不安全的特性。Java平台最初是为了解决联网的消费者设备的软件问题而诞生的。他被设计成了一个支持多种主机架构并且允许安全交付软件组件。为了满足这些要求,编译过的代码需要能在网络上传输,并被客户端执行,同时要保证客户端的允许安全。 2 | 3 | 随着万维网的普及,这些特性开始变得更为有趣。Web浏览器使数百万人能够以简单的方式上网并访问富媒体内容。无论您使用的是什么样的设备,什么样的网络调制解调器,您所看到和听到的内容基本相同。 4 | 5 | 网络爱好者很快就发现那些被html支持的内容文档限制太多。html的一些扩展,例如表单,更是凸显着这些限制,没有浏览器可以完全提供用户们想要的功能。答案是可扩展性。 6 | 7 | HotJava浏览器首先通过在html页面嵌入程序来展示java语言的有趣属性。程序被与html一起被无感知的被下载到浏览器中。在被浏览器接受之前,程序被仔细的检查他是否安全。就像html那样,编译过的代码同样也是与平台无关的。程序的行为方式相同,无论它们来自何处,或者它们被载入和运行的机器类型。 8 | 9 | 与java平台结合的浏览器已经不再被预先包含的功能所限制。动态页面的访问者们也被保证他们的电脑不会被内容所损害。开发者可以只编写一遍程序,而做到在各种支持java允许时的环境中运行。 -------------------------------------------------------------------------------- /1-Introduction/1.2_The_Java_Virtual_Machine.md: -------------------------------------------------------------------------------- 1 | Java虚拟机是java平台的基石。他是一套对于硬件与操作系统独立的技术组件,可以缩小编译代码的尺寸,并保护用户不收恶意程序的侵害。 2 | 3 | jvm是一个抽象的计算机。他就想一台真实的计算机一样,提供了一套在运行时操作内存的指令。使用虚拟机来实现编程语言是相当普遍的;最著名的虚拟机可能是UCSD Pascal的P-Code机器。 4 | 5 | 第一个执行JVM规范的虚拟机由SUN公司完成。在软件层面上模拟Java虚拟机的指令集,并托管于手持设备上,就像现代个人数字助理那样(Personal Digital Assistant)。Oracle当时分别在移动端,桌面端和服务端实现了java虚拟机,但是java虚拟机并不假定任何特定的实现技术,硬件或操作系统。它本质上并不是解释型,因为其也可以很好的通过编译而成为CPU的指令集。或也可以直接使用。 6 | 7 | Java虚拟机对于java语言一无所知,只是针对于特定的二进制格式--class文件。一个class文件中包含有jvm指令(bytecodes),符号表和其他一些辅助信息。 8 | 9 | 为了安全起见,java虚拟机对类文件中的代码强加了语法和结构约束。然而,任何具有可以用有效类文件表示的功能的语言都可以由Java虚拟机托管。由通用的,与机器无关的平台吸引,其他语言的实现者可以转向Java虚拟机作为其交付工具。 10 | 11 | 此处Java虚拟机指与Java SE 12平台兼容,并支持Java语言规范Java SE <*The Java Language Specification, Java SE 12 Edition*>. 12 | 13 | -------------------------------------------------------------------------------- /1-Introduction/1.3_Organization_of_the_Specification.md: -------------------------------------------------------------------------------- 1 | 第2章 java虚拟机的架构概观。 2 | 3 | 第3章 介绍了Java代码汇编为Java虚拟机的指令集。 4 | 5 | 第4章 类文件格式,这是一种独立于硬件和操作系统的二进制格式,用于表示已编译的类和接口。 6 | 7 | 第5章 Java虚拟机的启动以及类和接口的加载,链接和初始化。 8 | 9 | 第6章 按操作码助记符的字母顺序介绍Java虚拟机的指令集。 10 | 11 | 第7章 由操作码值索引的Java虚拟机操作码助记符表。 12 | 13 | 在第二版的*The Java® Virtual Machine Specification*中,第2章概述了Java编程语言,该语言旨在支持Java虚拟机的规范,但本身并不是规范的一部分。在 *The Java Virtual Machine Specification, Java SE 12 Edition*中,读者可以参考*The Java Language Specification, Java SE 12 Edition* 以获取更多关于java语言的信息。在必要时会有表格中的参考文献: (JLS §x.y) 14 | 15 | 在第二版的*The Java® Virtual Machine Specification*中,第8章详细介绍了解释Java虚拟机线程与共享主内存交互的底层操作。在 *The Java Virtual Machine Specification, Java SE 12 Edition*中读者可以参考*The Java Language Specification, Java SE 12 Edition* 的第17章以获取更多有关锁和线程的信息。第17章描述了JSR 133 Expert Group中的Java内存模型和线程规范。 16 | 17 | -------------------------------------------------------------------------------- /1-Introduction/1.4_Notation.md: -------------------------------------------------------------------------------- 1 | 在本规范中,我们所使用到的类和接口来自于 Java SE 平台的 API,无论何时,我们使用某个字母(譬如N)来表示某个类或接口时,默认都是指 java.lang 包下的那个类或接口,如果要描述其他包中的类或接口,我们将会使用全限定名。 2 | 3 | 无论何时,当我们提及某个类或接口的包是 java 或者它的子包,那就意味着这个类或接口是由引导类加载器进行加载的([§5.3.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.1))。 4 | 5 | 无论何时,我们提及某个包是 java 包的子包时,就意味着这个包是由引导类加载器所定义的。 6 | 7 | 在本书中,下面两种字体含义为: 8 | 9 | - `fixed width`这种小字体用于 JVM 数据类型、异常、错误、class 文件结构、序言码和 Java 代码。 10 | - 斜体用于描述 Java 虚拟机中的“汇编语言”,即操作码和操作数,也包括一些 JVM 运行时数据区域。有时也被用来说明一些新的条目和需要强调的内容。 11 | 12 | 非规范的信息,旨在阐明规范的,用小、缩进的文本表示。如 *This is non-normative information. It provides intuition, rationale, advice, examples, etc.* -------------------------------------------------------------------------------- /1-Introduction/1.5_Feedback.md: -------------------------------------------------------------------------------- 1 | 读者可以通过`jls-jvms-spec-comments@openjdk.java.net`来报告本规范中的技术错误和模糊之处。 2 | 3 | 关于通过 javac (java语言的编译器)生成和操纵的 class 文件的问题,可以将问题发送到`compiler-dev@openjdk.java.net`。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.1_The_class_File_Format.md: -------------------------------------------------------------------------------- 1 | jvm执行的被编译代码使用了一种独立于硬件和操作系统的二进制格式。一般来说(但不绝对)储存在class文件中。class文件格式精确定义了类或接口,并包含了特定于平台的目标文件格式中的字节排序等细节。 2 | 3 | 在第4章The `class` File Format中,详细描述了class文件细节。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.2_Data_Types.md: -------------------------------------------------------------------------------- 1 | 像java语言那样,java虚拟机操作两种类型的数据:原始类型(*primitive types*)和引用类型(*reference types*)。相应的,两种类型的值可以储存在变量中,作为参数传递,被方法返回,并在其上操作。 2 | 3 | Java虚拟机期望几乎所有类型检查都在运行时之前完成,这项工作一般由编译器来完成,而不是虚拟机本身。于引用类型不同的是,原始类型的值不需要被标记或以其他方式检查以在运行时确定它们的类型。对应的,Java虚拟机对不同的操作数类型使用不同的指令集来区分其操作数类型。例如, *iadd*, *ladd*, *fadd*和 *dadd*指令都是jvm真的两个数字类型相加而计算出一个数字类型结果,但是每个都是针对于不同的操作数类型:`int`, `long`, `float`和 `double`。有关Java虚拟机指令集中类型支持的介绍见 [§2.11.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.11.1)。 4 | 5 | Java虚拟机包含对对象的显式支持。对象可以是动态分配的类实例或数组。对对象的引用被视为具有Java虚拟机类型引用。类型引用的值可以被认为是指向对象的指针。同一个对象可能会有多个引用。对象始终通过类型引用的完成操作,传递和测试。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.3_Primitive_Types_and_Values/2.3.1_Integral_Types_and_Values.md: -------------------------------------------------------------------------------- 1 | Java虚拟机的整体类型( integral types )的值是: 2 | 3 | * btye -128 到 127 (-27 to 27 - 1) 包含。 4 | 5 | * short -32768 到 32767 (-215 to 215 - 1) 包含。 6 | 7 | * int -2147483648 到 2147483647 (-231 to 231 - 1) 包含。 8 | 9 | * long from -9223372036854775808 到 9223372036854775807 (-263 to 263 - 1) 包含。 10 | 11 | * char 0 到 65535 包含。 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.3_Primitive_Types_and_Values/2.3.2_Floating-Point_Types_Value_Sets_and_Values.md: -------------------------------------------------------------------------------- 1 | 浮点类型包括float和double,他们采用IEEE 754格式,分别为32bit单精度和64bit双精度,并且执行IEEE二进制浮点运算标准(ANSI / IEEE Std.754-1985,New York)中规定的操作。 2 | 3 | IEEE 754标准不仅包括正号和负号幅度数,而且也有正负零,正负无穷大和一个特殊的非数字值( Not-a-Number)(以下简称为“NaN”)。 NaN值用于表示某些无效操作的结果,例如将零除以零。NaN值用于表示某些无效操作的结果,例如将零除以零。 4 | 5 | 每一个Java虚拟机的实现都需要支持float值集和double值集两组浮点标准。此外,Java虚拟机的实现可以选择支持两个扩展指数浮点值集中的一个或两个,被称为*float-extended-exponent*值集和*double-extended-exponent*值集。在某些情况下,可以使用这些扩展指数值集代替标准值集来表示float或double类型的值。 6 | 7 | 任何浮点值集的有限非零值都可以表示为s·m·2(e - N + 1),其中s是+1或-1,m是小于2N的正整数,e是Emin = - (2K-1-2)和Emax = 2K-1-1之间的整数(包含)。其中N和K是依赖于值集的参数。某些值可以以多种方式以此形式表示;例如,假设值集中的值v可能使用s,m和e的某些值以此形式表示,那么如果m为偶数且e小于2K-1,则可以将m减半并将e加1以得到相同值v的第二种表示。如果m≥2N-1,则表格中的表示称为规范化(*normalized*);否则该表示被称为非规范化(*denormalized*)。如果值集中的值不能以m≥2N-1的方式表示,则该值被称为非规范化值,因为它没有规范化表示。 8 | 9 | 表 [2.3.2-A](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.2-140-A).总结了对两个必需和两个可选浮点值集的参数N和K(以及导出参数Emin和Emax)的约束。 10 | 11 | **Table 2.3.2-A. Floating-point value set parameters** 12 | 13 | | Parameter | float | float-extended-exponent | double | double-extended-exponent | 14 | | --------- | ----- | ----------------------- | ------ | ------------------------ | 15 | | *N* | 24 | 24 | 53 | 53 | 16 | | *K* | 8 | ≥ 11 | 11 | ≥ 15 | 17 | | *Emax* | +127 | ≥ +1023 | +1023 | ≥ +16383 | 18 | | *Emin* | -126 | ≤ -1022 | -1022 | ≤ -16382 | 19 | 20 | 如果实现支持一个或两个扩展指数值集,则对于每个支持的扩展指数值集,存在特定的依赖于实现的常量K,其值受表 [Table 2.3.2-A](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.2-140-A)的约束;该值K反过来决定了Emin和Emax的值。 21 | 22 | 四个值集中的每一个不仅包括它的有限非零值,还包括正零,负零,正无穷大,负无穷大和NaN的五个值。 23 | 24 | 请注意,表[Table 2.3.2-A](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.2-140-A) 中的约束是为了使float值集的每个元素都必须也是float-extended-exponent值集,double值集和double-extended-exponent值集的元素而设计的。同样,double值集的每个元素也必须是double-extended-exponent值集的元素。每个扩展指数值集的指数值范围都大于相应的标准值集,但精度都是一样的。 25 | 26 | 除了只有一个NaN值外,浮点值集的元素正是可以使用IEEE 754标准中定义的单浮点格式表示的值(IEEE 754指定224-2个不同的NaN值)。除NaN值外,double值集的元素正是可以使用IEEE 754标准中定义的双浮点格式表示的值(IEEE 754规定了253-2个不同的NaN值)。但请注意,此处定义的float-extended-exponent和double-extended-exponent值集的元素与可使用IEEE 754单扩展和双扩展格式表示的值不对应。除了必须以类文件格式([§4.4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.4)), [§4.4.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.5))表示浮点值的情况外,本规范不要求对浮点值集的值进行特定表示。 27 | 28 | float,float-extended-exponent,double和double-extended-exponent值集不是类型。对于Java虚拟机的实现来说,使用float值集的元素来表示float类型的值总是正确的;然而,在实现中的某些情况下使用 float-extended-exponent 值集的元素是被允许的。同样的,对于实现来说,使用double值集的元素来表示double类型的值总是正确的,在某些上下文中,允许使用double-extended-exponent值集的元素。 29 | 30 | 除那些NaN外,浮点值集的值是有序的。当从最小到最大排列时,它们是负无穷大,负有限值,正负零,正有限值和正无穷大。 31 | 32 | 浮点正零和浮点负零在比较时是相等的,但还有其他操作可以区分它们;例如,将1.0除以0.0会产生正无穷大,但将1.0除以-0.0会产生负无穷大。 33 | 34 | NaN是无序的,因此,如果其操作数中的任何一个或两个都是NaN,则数值比较和数值相等测试的值总为false。特别的,当且仅当值为NaN时,值自身的数值相等性的测试结果为false。如果任一操作数是NaN,则对数值不等式的测试值为true。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.3_Primitive_Types_and_Values/2.3.3_The_returenAddress_Type_and_Values.md: -------------------------------------------------------------------------------- 1 | *returnAddress* 类型由java虚拟机中的jsr,ret和jsr_w指令使用([§*jsr*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.jsr), [§*ret*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.ret), [§*jsr_w*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.jsr_w))。*returnAddress*类型的值为指向JVM指令操作数的指针。与数字原始类型不同,*returnAddress*不与java语言中的类型对应,也无法通过正在运行的程序进行修改。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.3_Primitive_Types_and_Values/2.3.4_The_boolean_Type.md: -------------------------------------------------------------------------------- 1 | 尽管JVM定义了布尔类型,但其仅只为他提供非常有限的支持。Java虚拟机中没专门用于对布尔值操作的指令,Java编程语言中对布尔值进行操作的表达式被编译为使用Java虚拟机int数据类型的值。 2 | 3 | Java虚拟机直接支持布尔数组。newarray([§*newarray*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.newarray))指令可以用来创建boolean数组。使用对byte数组操作的指令*baload*和*bastore*来完成对boolean数组的访问和修改([§*baload*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.baload), [§*bastore*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.bastore))。 4 | 5 | 在Oracle的JVM实现中,java中的boolean数组被编码为JVM中的byte数组,每个boolean元素占8bit。 6 | 7 | 对boolean数组元素,Java虚拟机使用1表示true,0表示false。其中Java编程语言布尔值由编译器映射到Java虚拟机类型int的值,编译器必须使用相同的编码。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.3_Primitive_Types_and_Values/Primitive_Types_and_Values.md: -------------------------------------------------------------------------------- 1 | JVM支持的原始数据类型有数字类型,布尔类型 ([§2.3.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.4))和返回地址类型(returnAddress [§2.3.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.3))。 2 | 3 | 数字类型包括整体类型型( *integral types* [§2.3.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.1))和浮点型( *floating-point types* [§2.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.2))。 4 | 5 | 整体类型有: 6 | 7 | * byte 其值为8位有符号的二进制补码整数。默认值是0 8 | * short 其值为8位有符号的二进制补码整数。默认值是0 9 | * int 其值为32位有符号的二进制补码整数。默认值是0 10 | * long 其值为64位有符号的二进制补码整数。默认值是0 11 | * char 其值为16位无符号整数,表示为Unicode编码,由UTF-16编码,默认值为null的代码点(`'\u0000'`) 12 | 13 | 浮点类型有: 14 | 15 | * float 其值为浮点值集的元素集或浮点扩展指数( float-extended-exponent)值集(如果支持),默认值为正零。 16 | * double 其值为双精度浮点值集的元素集或双精度浮点扩展指数(double-extended-exponent)值集(如果支持),默认值为正零。 17 | 18 | 布尔类型的值对true和false进行编码,默认值为false。 19 | 20 | *Java®虚拟机规范的第一版没有将布尔值视为Java虚拟机类型。然而,布尔值在Java虚拟机中的支持有限,Java®虚拟机规范的第二版通过将布尔值视为一种类型来澄清该问题。* 21 | 22 | returnAddress类型的值是指向Java虚拟机指令的操作码的指针。在原始类型中,只有returnAddress类型与Java编程语言类型没有直接关联。 23 | 24 | -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.4_Reference_Types_and_Values.md: -------------------------------------------------------------------------------- 1 | 共有三种引用类型:class,array,和interface。它们的值分别是对动态创建的类实例,数组或类实例或实现接口的数组的引用。 2 | 3 | 数组类型由具有单个维度的元素类型组成(其长度不由其类型给出)。数组中的元素类型可以也是一个数组类型。如果从任何数组类型开始,考虑其组件类型,然后(如果这也是数组类型)该类型的组件类型,...,最终必然达到不是数组类型的组件类型;这称为数组类型的元素类型。数组类型的元素类型必须是基本类型,类类型或接口类型。 4 | 5 | 引用类型也可以是特殊的null引用,表明其不指向任何对象,在这里表示为*null*。null引用没有运行时初始类型,且可以转换为任何类型。引用类型的默认值为*null*。 6 | 7 | 该规范没有强制要求编码null的具体值。 8 | 9 | -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.5_Run-Time_Data_Areas/2.5.1_The_pc_Register.md: -------------------------------------------------------------------------------- 1 | Java虚拟机支持多线程在同一时间运行(JLS §17)。每一个JVM线程都有一个自己的pc寄存器(程序计数器)。在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6))。如果当前方法不是native的话,pc寄存器包含当前正在执行的Java虚拟机指令的地址。如果当前线程正常执行的方法是native的话,该pc寄存器的值是undefined。JVM中的pc寄存器的空间足够放下一个returnAddress类型或特定平台下的native指针。 2 | -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.5_Run-Time_Data_Areas/2.5.2_Java_Virtual_Machine_Stacks.md: -------------------------------------------------------------------------------- 1 | 每一个JVM线程都有一个随线程启动创建的私有的JVM栈。Java虚拟机堆栈存储帧([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6))。一个JVM栈与其他语言中的常规栈比较类似,如C语言中,他包含局部变量和部分结果,并在方法调用和返回时被用到。由于除了推送和弹出帧之外,JVM永远不会直接操作Java虚拟机堆栈,因此栈帧可以由堆分配。Java虚拟机堆栈的内存不需要是连续的。 2 | 3 | 在Java®虚拟机规范的第一版中,Java虚拟机栈称为Java栈。 4 | 5 | 此规范允许Java虚拟机堆栈具有固定大小或根据计算的需要动态扩展和收缩。如果Java虚拟机栈具有固定大小,则可以在创建该栈时独立选择每个Java虚拟机栈的大小。 6 | 7 | Java虚拟机可以为程序员或用户提供对Java虚拟机堆栈的初始大小的控制的方式。以及,在动态扩展或收缩Java虚拟机堆栈的情况下,控制最大和最小容量。 8 | 9 | 以下异常条件与Java虚拟机堆栈相关联: 10 | 11 | * **如果线程中的计算需要比允许的更大的Java虚拟机栈,则Java虚拟机会抛出StackOverflowError。** 12 | * **如果可以动态扩展Java虚拟机堆栈,并尝试进行扩展,但可用内存不足以实现扩展,或者,如果可以使内存不足以为新线程创建初始Java虚拟机堆栈,则Java虚拟机会抛出OutOfMemoryError。** -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.5_Run-Time_Data_Areas/2.5.3_Heap.md: -------------------------------------------------------------------------------- 1 | Java虚拟机中的堆在所有Java虚拟机线程之间共享。堆是运行时数据区,所有的类实例和数组都位于这里。 2 | 3 | 堆是在虚拟机启动时创建的。对象在的堆中占用的内存由自动存储管理系统(称为垃圾收集器)回收;对象永远不会被显式释放。Java虚拟机没有假定特定类型的自动存储管理系统,所以实现者可以根据的系统要求选择存储管理技术。堆可以具有固定大小,或者可以根据计算的需要进行扩展或收缩,且堆的内存不需要连续。 4 | 5 | Java虚拟机实现可以为程序员或用户提供对堆的初始大小的控制,或控制最大和最小堆大小如果可以动态扩展的话。 6 | 7 | 以下异常情况与堆相关联: 8 | 9 | **如果计算需要的堆数超过自动存储管理系统可用的堆,则Java虚拟机会抛出OutOfMemoryError。** -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.5_Run-Time_Data_Areas/2.5.4_Method_Area.md: -------------------------------------------------------------------------------- 1 | Java虚拟机中的方法区是与其所在JVM所有线程共享的。方法区域类似于传统语言的编译代码的存储区域或类似于操作系统进程中的“文本”段("text" segment)。他保存了每个class的结构,例如运行时常量池,属性,方法数据以及构造函数和方法的代码,包括类和接口初始化以及实例初始化中使用的特殊方法 ([§2.9](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.9))。 2 | 3 | 方法区在JVM启动时被创建。虽然方法区域在逻辑上是堆的一部分,一些简单的实现可以选择不对他进行垃圾回收或压缩。本规范未规定方法区域的位置或用于管理编译代码的策略。方法区域可以是固定大小,或者可以根据计算的需要进行扩展,如果不需要更大的方法区域,则可以缩小方法区域。方法区域的内存不需要是连续的。 4 | 5 | *Java虚拟机实现可以提供程序员或用户对方法区域的初始大小的控制,以及在可变大小方法区的情况下,可以控制最大和最小方法区大小。* 6 | 7 | 以下异常条件与方法区相关联: 8 | 9 | **如果无法使方法区域中的内存满足分配请求,则Java虚拟机将抛出OutOfMemoryError。** 10 | 11 | -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.5_Run-Time_Data_Areas/2.5.5_Run-time_Constant_Pool.md: -------------------------------------------------------------------------------- 1 | 运行时常量池是类文件中的constant_pool表的类或接口运行时表现 ([§4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4))。它包含几种常量,从编译时已知的数字文字到只能在运行时解析的方法和字段引用。运行时常量池提供类似于传统编程语言的符号表的功能,尽管它包含比典型符号表更宽范围的数据。 2 | 3 | 每个运行时常量池都是从Java虚拟机的方法区域 ([§2.5.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.5.4))分配的。当Java虚拟机创建类或接口 ([§5.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3)) 时,将构造类或接口的运行时常量池。 4 | 5 | 以下异常条件与类或接口的运行时常量池的构造相关联: 6 | 7 | - **创建类或接口时,如果运行时常量池的构造需要的内存比Java虚拟机的方法区域中可用的内存多,则Java虚拟机会抛出OutOfMemoryError。** 8 | 9 | 有关构造运行时常量池的信息,请参见 [§5 (*Loading, Linking, and Initializing*)](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html)。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.5_Run-Time_Data_Areas/2.5.6_Native_Method_Stacks.md: -------------------------------------------------------------------------------- 1 | Java虚拟机的实现可以使用传统的堆栈,俗称“C堆栈”,以支持本地方法(用Java编程语言以外的语言编写的方法)。本地方法堆栈也可以通过用诸如C语言的Java虚拟机的指令集的解释器的实现来使用。无法加载本地方法且本身不依赖于传统堆栈的Java虚拟机实现无需提供本机方法堆栈。如果提供的话,则通常在创建每个线程时为每个线程分配本地方法堆栈。 2 | 3 | 此规范允许本地方法堆栈具有固定大小或根据计算的需要动态扩展和收缩。如果本地方法堆栈具有固定大小,则可以在创建该堆栈时独立地选择每个本地方法堆栈的大小。 4 | 5 | Java虚拟机实现可以为程序员或用户提供对本地方法堆栈的初始大小的控制,以及在不同大小的本地方法堆栈的情况下,控制最大和最小方法堆栈大小。 6 | 7 | 以下异常条件与本地方法堆栈相关联: 8 | 9 | - **如果线程中的计算需要比允许的更大的本地方法堆栈,则Java虚拟机会抛出StackOverflowError。** 10 | - **如果可以动态扩展本地方法堆栈并尝试本地方法堆栈扩展但可用内存不足,或者如果可用内存不足以为新线程创建初始本地方法堆栈,则Java虚拟机会抛出OutOfMemoryError 。** 11 | 12 | -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.5_Run-Time_Data_Areas/Run-Time_Data_Areas.md: -------------------------------------------------------------------------------- 1 | Java虚拟机定义了在程序执行期间使用的各种运行时数据区域。其中一些数据区域是在Java虚拟机启动时创建的,且仅在Java虚拟机退出时销毁。其他数据区域是每个线程独立的。线程数据区域是随线程的创建和销毁的。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.6_Frames/2.6.1_Local_Variables.md: -------------------------------------------------------------------------------- 1 | 每个帧([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6)) 都包含一个称为局部变量的变量数组。帧的局部变量数组的长度在编译时确定,并以类或接口的二进制表示形式提供,同时提供与帧相关的方法的代码 ([§4.7.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7.3))。 2 | 3 | 单个局部变量可以包含boolean,byte,char,short,int,float,reference或returnAddress类型的值。两个局部变量可以存储long或double类型的值。 4 | 5 | 通过索引来解决局部变量。第一个局部变量的索引为零。当且仅当该整数在0到小于局部变量数组的大小之间的值时,整数才被认为是局部变量数组的索引。 6 | 7 | long类型或double类型的值占用两个连续的局部变量。只能使用较小的索引来处理这样的值。例如,存储在索引n的局部变量数组中的double类型的值实际上占用索引为n和n + 1的局部变量;但是,尽管可以储存,但无法加载索引n + 1处的局部变量。因为,这样做会使局部变量n初的内容无效。 8 | 9 | Java虚拟机不需要n为偶数。用直观的术语来说,long和double类型的值不需要在局部变量数组中进行64位对齐。实现者可以自主选择如何表示那些需要占用两个局部变量的值。 10 | 11 | 在方法调用时,jvm使用局部变量去传递参数。在调用类方法时,所有参数都将从局部变量0开始位置的连续的传递。在调用实例方法时,局部变量0始终为当前被调用实例方法的对象引用(Java中)。随后其他参数由局部变量1开始的连续变量传递。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.6_Frames/2.6.2_Operand_Stacks.md: -------------------------------------------------------------------------------- 1 | 每一个帧 ([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6)) 都包含一个后进先出(LIFO)的操作数栈。其最大深度在编译期由帧 ([§4.7.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7.3))相关代码给出。 2 | 3 | 在上下文清楚的地方,我们将当前帧的操作数堆栈简称为操作数堆栈。 4 | 5 | 在帧被创建时,其对应的操作数栈为空。JVM提供了一些用以将局部变量、属性中的常量或变量压入操作数栈的指令。其他Java虚拟机指令从操作数堆栈中获取操作数,对其进行操作,然后将结果压回操作数堆栈。操作数堆栈还用于传递给方法参数并接收方法结果。 6 | 7 | 例如,iadd ([§*iadd*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.iadd)) 指令用以将两个int值相加。将要被相加的int值需要位于操作数栈栈顶(由位于该指令前的其他指令压入),iadd指令将他们弹出,并做加法运算,最后将结果压会操作数栈。子运算可嵌套在操作数堆栈上,从而产生可被包含计算使用的值。 8 | 9 | 操作数堆栈上的每个条目都可以保存任何Java虚拟机类型的值,包括long类型或double类型的值。 10 | 11 | 操作数堆栈中的值必须以适合其类型的方式进行操作。例如,不可能推入两个int值,然后将它们视为long值,或推入两个float值,然后使用iadd指令将它们相加。少量的Java虚拟机指令(dup指令([§*dup*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.dup))和swap([§*swap*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.swap)))在运行时数据区域上以原始值运行,而与它们的特定类型无关。这些指令被定义为不能用于修改或破坏单个值。通过类文件验证([§4.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.10))来保证操作数堆栈操作的这些限制。 12 | 13 | 在任何时间点,操作数堆栈都具有关联的深度,其中long或double类型的值对该深度占用两个单位,而任何其他类型的值则占用一个单位深度。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.6_Frames/2.6.3_Dynamic_Linking.md: -------------------------------------------------------------------------------- 1 | 为了支持方法代码中的动态链接,每一个帧([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6)) 都包含有一个指向运行时常量池 ([§2.5.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.5.5))中当前方法类型的引用。方法的类文件代码是指被调用的方法和通过符号引用访问的变量。动态链接在必要时会通过加载类以解析尚未定义的符号,将变量访问转换为与这些变量的运行时位置关联的存储结构中的偏移量,从而将这些符号引用转换为对具体方法的引用。 2 | 3 | 方法和变量的后期绑定使方法使用的其他类的更改不太可能破坏此代码。 4 | 5 | -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.6_Frames/2.6.4_Normal_Method_Invocation_Completion.md: -------------------------------------------------------------------------------- 1 | 如果一个方法调用未出现异常 ([§2.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.10)) ,且没有显示的使用throw语句抛出异常,那么其调用为正常完成。当被调用的方法执行任一返回指令([§2.11.8](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.11.8))时,被调用方法法会向调用方返回值,对返回指令必须与要返回的值的类型向匹配(如果有返回的话)。 2 | 3 | 在这种情况下,使用当前帧([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6))来恢复调用程序的状态,包括其局部变量和操作数栈,并适当增加调用程序的程序计数器以跳过方法调用指令。执行这些操作通常在调用方法的帧中,并将返回值(如果有)压入该帧的操作数栈。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.6_Frames/2.6.5_Abrupt_Method_Invocation_Completion.md: -------------------------------------------------------------------------------- 1 | 如果方法内执行的Java虚拟机指令导致Java虚拟机抛出异常 ([§2.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.10)),且该方法未处理该异常,则方法调用将立即结束。执行athrow指令([§*athrow*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.athrow)) 会显式引发异常,如果当前方法未捕获该异常,则同样会使方法调用立即结束。此类完成的方法调用永远不会向其调用者返回值。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.6_Frames/Frames.md: -------------------------------------------------------------------------------- 1 | 栈帧用于存储数据和部分结果,以及执行动态链接,返回方法的值以及分发异常。 2 | 3 | 当一个方法被调用时,便会创建一个新的帧。当一个方法调用结束时(无论是正常结束或是异常结束,例如抛出一个未捕获的异常),对应的栈帧会被销毁。帧是位于JVM栈中 ([§2.5.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.5.2)) ,由线程所创建的。每个帧都有他独有的局部变量数组([§2.6.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6.1))和自己的操作栈 ([§2.6.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6.2))和指向当前类方法运行时常量池的引用。 4 | 5 | 可以使用附加的特定于实现的信息来扩展帧,例如调试信息。 6 | 7 | 局部变量数组和操作数堆栈的大小在编译时确定,并与与帧相关的方法的代码一起提供([§4.7.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7.3))。因此,帧数据结构的大小仅取决于Java虚拟机的实现,并且可以在方法调用的同时分配内存。 8 | 9 | 只有执行方法的帧在给定控制线程中的任何点处都是活动的。该帧被称为当前帧,并且其方法被称为当前方法。定义当前方法的类是当前类。局部变量和操作数堆栈的操作通常参考当前帧。 10 | 11 | 如果帧的方法调用另一个方法或其方法完成,则该帧将不再是当前帧。调用方法时,会创建一个新帧,并在控制转移到新方法时变为当前帧。在方法返回时,当前帧将其方法调用的结果(如果有)传递回前一帧。然后当前一帧成为当前帧并丢弃该帧。 12 | 13 | 请注意,由线程创建的帧对于该线程是本地的,并且不能被任何其他线程引用。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.7_Representation_of_Objects.md: -------------------------------------------------------------------------------- 1 | Java虚拟机不要求对象具有任何特定的内部结构。 2 | 3 | 在Oracle对Java虚拟机的某些实现中,对类实例的引用是指向本身是一对指针的句柄的指针:一个指向包含该对象的方法的表,另一个指向代表该对象类型的Class对象的指针,另一个指向堆中为对象数据分配的内存。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.8_Floating_Point_Arithmetic/2.8.1_Java_Virtual_Machine_Floating_Point_Arithmetic_and_IEEE_754.md: -------------------------------------------------------------------------------- 1 | Java中支持的浮点运算与IEEE 754标准中的主要不同有: 2 | 3 | - Java虚拟机的浮点操作不会引发异常,陷阱或其他形式的信号以表明IEEE 754中的无效操作,如被零除,上溢出,下溢出或不精确的特殊情况。 并且Java虚拟机没有NaN值。 4 | - Java虚拟机不支持IEEE 754信令浮点比较。 5 | - Java虚拟机的舍入操作始终使用IEEE 754中舍入到最近模式。IEEE 754的默认模式会将结果四舍五入到最接近的可表示值,并用最低有效位为零的值舍入。但是,Java虚拟机指令将浮点类型的值转换为整数类型的值向零舍入。Java虚拟机不提供任何更改浮点舍入模式的方法。 6 | - 除了double和double-extended-exponent值集可以支持单一扩展格式之外,Java虚拟机不支持IEEE 754单扩展或双扩展格式。可以可选支持的float扩展指数和double扩展指数值集与于IEEE 754扩展格式的值并不一致:IEEE 754扩展格式需要扩展的精度以及扩展的指数范围。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/2.8_Floating_Point_Arithmetic/Floating_Point_Arithmetic.md: -------------------------------------------------------------------------------- 1 | Java虚拟机包含IEEE标准二进制浮点算术 (ANSI/IEEE Std. 754-1985, New York)中指定的浮点算术的子集。 -------------------------------------------------------------------------------- /2-The_Structure_of_The_Java_Virtual_Machine/The_Structure_of_the_Java_Virtual_Machine.md: -------------------------------------------------------------------------------- 1 | 本文档描述了一个抽象的虚拟机,并不是特定的某种JVM实现。 2 | 3 | 去正确的实现一个虚拟机,你只需要能够读取class文件格式并且正确的执行其指定的操作。由于具体实现细节并不包含在java虚拟机规范中,所以实现着可以尽情的发挥其创造力。举例来说,内存层面的运行时数据区,gc算法的使用以及任何对jvm指令的内部优化(例如转换成机器码的过程),均由实现着自行决定。 4 | 5 | 本规范中对Unicode的所有引用都是针对Unicode标准版本11.0.0给出的。见`http://www.unicode.org/`。 6 | 7 | -------------------------------------------------------------------------------- /4-The_class_File_Format/4.1_The_ClassFile_Structure.md: -------------------------------------------------------------------------------- 1 | 一个class文件可以用以下classFile结构体描述: 2 | 3 | ```C 4 | ClassFile { 5 | u4 magic; 6 | u2 minor_version; 7 | u2 major_version; 8 | u2 constant_pool_count; 9 | cp_info constant_pool[constant_pool_count-1]; 10 | u2 access_flags; 11 | u2 this_class; 12 | u2 super_class; 13 | u2 interfaces_count; 14 | u2 interfaces[interfaces_count]; 15 | u2 fields_count; 16 | field_info fields[fields_count]; 17 | u2 methods_count; 18 | method_info methods[methods_count]; 19 | u2 attributes_count; 20 | attribute_info attributes[attributes_count]; 21 | } 22 | ``` 23 | 24 | 下面将单独介绍每一项的含义: 25 | 26 | magic 27 | 28 | ​ class文件中定义的魔术值,在这里他的值是 `0xCAFEBABE`。 29 | 30 | minor_version,major_version 31 | 32 | ​ 这个两个值分别表示class文件的次版本号和主版本号。他们共同决定了class文件格式的版本。如果一个class文件的major version是M,minor version为m,我们则称这个class文件的版本为M.m。 33 | 34 | ​ 符合Java SE N的Java虚拟机实现必须完全支持表 [Table 4.1-A](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1-200-B.2)中为Java SE N指定的类文件格式的主要版本。其中,A...B表示主版本A到B之间(闭区间)。Corresponding major version列表示每个Java SE版本引入的主版本号,即可以接受包含该major_version项目的类文件的第一个版本。对于早期版本,将显示JDK版本而不是Java SE版本。 35 | 36 | **Table 4.1-A. class file format major versions** 37 | 38 | | Java SE | Corresponding major version | Supported major versions | 39 | | ------- | --------------------------- | ------------------------ | 40 | | 1.0.2 | 45 | 45 | 41 | | 1.1 | 45 | 45 | 42 | | 1.2 | 46 | 45 .. 46 | 43 | | 1.3 | 47 | 45 .. 47 | 44 | | 1.4 | 48 | 45 .. 48 | 45 | | 5.0 | 49 | 45 .. 49 | 46 | | 6 | 50 | 45 .. 50 | 47 | | 7 | 51 | 45 .. 51 | 48 | | 8 | 52 | 45 .. 52 | 49 | | 9 | 53 | 45 .. 53 | 50 | | 10 | 54 | 45 .. 54 | 51 | | 11 | 55 | 45 .. 55 | 52 | | 12 | 56 | 45 .. 56 | 53 | 54 | ​ 对于class文件来说,如果major_version为56或以上,其minor_version应为0到65535之间。 55 | 56 | ​ 如果major_version为45到55之间(闭区间),其minor_version可以是任何值。 57 | 58 | ​ 有必要保证对类文件格式版本的历史问题。 JDK 1.0.2支持45.0到45.3版本。JDK 1.1支持45.0到45.65535版本。当JDK 1.2引入对主要版本46的支持时,该主要版本支持的唯一次要版本是0。后续JDK继续在引入对新主要版本时也延续了这一做法,在新的主要版本下仅有为0的次要版本。最后,在Java SE 12中引入预览功能(见下文)触发了类文件格式的次要版本的标准角色,因此JDK 12在主要版本56下支持0和65535的次要版本。后续JDK引入了对N的支持.0和N.65535其中N是已实现的Java SE平台的相应主要版本。 59 | 60 | ​ java SE会提供一些抢鲜特性。在基于java SE 12规范之后的虚拟机实现必须仅支持所有的当前版本的抢先版功能。并且,其抢鲜的功能必须是默认关闭的,并提供打开所有抢鲜功能的方式,然而,去关闭或打开其中一个或多个预览特性的方式并不是必须的。 61 | 62 | ​ 如果一个class文件是基于大于se12的预览版本构建的,那么他的major_version应该基于其se版本 [Table 4.1-A](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1-200-B.2),并且minor_version为65535。 63 | 64 | ​ 一个大于se 12虚拟机的实现必须满足以下条件: 65 | 66 | - 如果一个class文件基于预览特性,那么他只能由开启预览的java se所加载。 67 | 68 | - 一个基于预览特性特class文件不能被其他版本的java se加载。 69 | 70 | - 虚拟机无论是否启用了Java SE 的预览功能,都可以加载不依赖于任何Java SE版本的预览功能的类文件。 71 | 72 | 73 | 74 | constant_pool_count 75 | 76 | ​ constant_pool_count的值比constant_pool表项的个数大一。由于long和double类型的存在[§4.4.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.5),constant_pool索引应大于0小于constant_pool_count。 77 | 78 | 79 | 80 | constant_pool[] 81 | 82 | ​ constant_pool是一个结构表[§4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4),表示各种字符串常量,类和接口名称,字段名称以及在ClassFile结构及其子结构中引用的其他常量。每个constant_pool表条目的格式由其第一个“标记”字节标识。 83 | 84 | 85 | 86 | access_flags 87 | 88 | ​ access_flags的值用来标记类或接口中属性的访问权限,不同的权限以位图的形式表示。每一种标识的含义在表[Table 4.1-B](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1-200-E.1)中说明。 89 | 90 | **Table 4.1-B. Class access and property modifiers** 91 | 92 | | Flag Name | Value | Interpretation | 93 | | ---------------- | ------ | ------------------------------------------------------------ | 94 | | `ACC_PUBLIC` | 0x0001 | Declared `public`; may be accessed from outside its package. | 95 | | `ACC_FINAL` | 0x0010 | Declared `final`; no subclasses allowed. | 96 | | `ACC_SUPER` | 0x0020 | Treat superclass methods specially when invoked by the *invokespecial* instruction. | 97 | | `ACC_INTERFACE` | 0x0200 | Is an interface, not a class. | 98 | | `ACC_ABSTRACT` | 0x0400 | Declared `abstract`; must not be instantiated. | 99 | | `ACC_SYNTHETIC` | 0x1000 | Declared synthetic; not present in the source code. | 100 | | `ACC_ANNOTATION` | 0x2000 | Declared as an annotation type. | 101 | | `ACC_ENUM` | 0x4000 | Declared as an `enum` type. | 102 | | `ACC_MODULE` | 0x8000 | Is a module, not a class or interface. | 103 | 104 | 其中,ACC_MODULE表示改class文件定义了一个module,而不是class或interface。如果设置的ACC_MODULE标识,其将拥有特定的规则(在本节尾会给出)。如果ACC_MODULE未设置,则适用当前段落下面的规则。 105 | 106 | 接口若被设置ACC_INTERFACE标识。如果没有该标识,则该class文件为定义class。而不是interface或module。 107 | 108 | ACC_INTERFACE与ACC_ABSTRACT标识不能同时存在。并且如果设置了ACC_INTERFACE,则ACC_FINAL,ACC_SUPER,ACC_ENUM和ACC_MODULE标识一定未被设置。 109 | 110 | 如果ACC_INTERFACE未被设置,则可以设置表[Table 4.1-B](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1-200-E.1)中除ACC_ANNOTATION和ACC_MODULE的其他属性。然而,一个class文件不能同时拥有ACC_FINAL和ACC_ABSTRACT标识 (JLS §8.1.1.2)。 111 | 112 | 对于出现在class或interface中的ACC_SUPER标识,invokespecial([§*invokespecial*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.invokespecial))指令会有两种语义。Java虚拟机指令集的编译器应设置ACC_SUPER标志。在Java SE 8及以下版本中,Java虚拟机认为要在每个类文件中设置ACC_SUPER标志,而不管类文件中的标志和类文件的版本。 113 | 114 | ACC_SUPER标志的存在是为了与旧编译器而向后兼容。在JDK 1.0.2之前,编译器生成了access_flags,而目前用于表示ACC_SUPER的位没有赋值,如果有赋值,Oracle的Java虚拟机也会忽略。 115 | 116 | ACC_SYNTHETIC标识标识该class或interface是由编译器生成的,而不是来自源码。 117 | 118 | 对于注解类型(JLS §9.6) ,其一定拥有ACC_ANNOTATION标识和ACC_INTERFACE标识。 119 | 120 | ACC_ENUM标识表示该类或其父类是枚举类型 (JLS §8.9)。 121 | 122 | 表 [Table 4.1-B](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1-200-E.1) 中未被用到的bit位都为未来保留。他们应该都设置为零,且会被JVM所忽略。 123 | 124 | 125 | 126 | this_class 127 | 128 | this_class的值必须是constant_pool中的一个有效索引。其对应索引处常量池中的结构体必须是CONSTANT_Class_info([§4.4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.1))结构,表示该class文件所定义的类或接口。 129 | 130 | 131 | 132 | super_class 133 | 134 | ​ 对于类来说,其super_class的值必须为0或constant_pool中的有效索引。如果super_class值为非0,则对应常量池中的表项一定为表示该文件所定义类的直接父类的CONSTANT_Class_info结构。直接超类或其任何超类都不能在其ClassFile结构的access_flags项中设置ACC_FINAL标志。 135 | 136 | ​ 如果其super_class值为0,这该class文件表示的类一定为Object,因为Object类是java中唯一一个没有直接父类的类。 137 | 138 | ​ 对接口来说,其super_class的值总是一个在constant_pool中的一个合法索引。该索引处的constant_pool条目必须是表示Object类的CONSTANT_Class_info结构。 139 | 140 | 141 | 142 | interfaces_count 143 | 144 | ​ 该值给出了当前类或接口的直接父接口个数。 145 | 146 | 147 | 148 | interfaces[] 149 | 150 | ​ 每个在interfaces数组中的值必须是constant_pool表中的一个有效索引。对于constant_pool中的每一个interfaces数组第中下标为i(0 <= i <=interfaces_count )的元素来说,必须是CONSTANT_Class_info结构,从左到右的顺序表示作为此类或接口类型的直接超接口的接口。 151 | 152 | 153 | 154 | fields_count 155 | 156 | ​ 该值给出fields表中field_info结构体的个数。field_info结构表示由此类或接口类型声明的所有字段,包括类变量和实例变量。 157 | 158 | 159 | 160 | fields[] 161 | 162 | ​ fields表中的每个值必须是field_info结构([§4.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.5)),给出该类或接口中字段的完整描述。fields表仅包括由此类或接口声明的那些字段。它不包括表示从超类或超接口继承的字段的项。 163 | 164 | 165 | 166 | methods_count 167 | 168 | ​ methods_count项的值给出了methods表中method_info结构的数量。 169 | 170 | 171 | 172 | methods[] 173 | 174 | ​ methods表中的每个值必须是method_info结构([§4.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.6)) ,它给出了此类或接口中方法的完整描述。如果在method_info结构的access_flags项中未设置ACC_NATIVE和ACC_ABSTRACT标志,则还提供实现该方法的Java虚拟机指令。method_info结构表示此类或接口类型声明的所有方法,包括实例方法,类方法,实例初始化方法(([§2.9.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.9.1))以及任何类或接口初始化方法([§2.9.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.9.2))。methods表不包括表示从超类或超接口继承的方法的项。 175 | 176 | 177 | 178 | attributes_count 179 | 180 | ​ attributes_count项的值给出了此类的属性表中的属性数。 181 | 182 | 183 | 184 | attributes[] 185 | 186 | ​ 属性表的每个值必须是attribute_info结构([§4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7))。 187 | 188 | ​ 表 [Table 4.7-C](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7-320)列出了位于ClassFile结构中attributes表的属性。 189 | 190 | ​ 有关定义出现在ClassFile结构的属性表中的属性的规则在 [§4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7)中给出。 191 | 192 | ​ 有关ClassFile结构的属性表中的非预定义属性的规则在[§4.7.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7.1)中给出。 193 | 194 | 如果在access_flags项中设置了ACC_MODULE标志,则可以不设置access_flags项中的其他标志,并且以下规则适用于ClassFile结构的其余部分: 195 | 196 | - major_version,minor_version:≥53.0(即Java SE 9及以上版本) 197 | - this_class:module-info 198 | - super_class,interfaces_count,fields_count,methods_count:zero 199 | - attributes:必须存在一个Module属性。除Module,ModulePackages,ModuleMainClass,InnerClasses,SourceFile,SourceDebugExtension,RuntimeVisibleAnnotations和RuntimeInvisibleAnnotations之外,不会出现任何预定义的属性([§4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7))。 200 | 201 | ​ 202 | 203 | ​ -------------------------------------------------------------------------------- /4-The_class_File_Format/4.2_Names/4.2.1_Binary_Class_and_Interface_Names.md: -------------------------------------------------------------------------------- 1 | 出现在类文件结构中的类和接口名称始终以称为二进制名称的完全限定形式表示(JLS§13.1)。这些名称始终表示为CONSTANT_Utf8_info结构([§4.4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.7)),因此可以无限制的使用Unicode进行编码。类和接口名称所引用的结构为CONSTANT_NameAndType_info([§4.4.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.6)),这些结构的名称是其描述符([§4.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.3))的一部分,并且他们都属于CONSTANT_Class_info结构的一部分([§4.4.1)](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.1)。 2 | 3 | 由于历史原因,出现在类文件结构中的二进制名称的语法与JLS§13.1中记录的二进制名称的语法不同。在此内部形式中,通常将构成二进制名称的标识符分隔的ASCII句点(.)替换为ASCII正斜杠(/)。标识符本身必须是非限定名称([§4.2.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.2.2))。 4 | 5 | 例如,Thread类的普通二进制名称是java.lang.Thread。在类文件格式的描述符中使用的内部形式中,使用字符串java/lang/Thread的CONSTANT_Utf8_info结构来表示对类Thread的名称的引用。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.2_Names/4.2.2_Unqualified_Names.md: -------------------------------------------------------------------------------- 1 | 方法,字段,局部变量和形式参数的名称存储为非限定名称。非限定名称必须至少包含一个Unicode代码点,并且不得包含任何ASCII字符。 ; [/(即句号或分号或左方括号或正斜杠)。 2 | 3 | 方法名称进一步受到限制,除了特殊方法名称(§2.9)之外,它们不能包含ASCII字符<或>(即左尖括号或右尖括号) 。 4 | 5 | *请注意,字段名称或接口方法名称可以是,但是没有方法调用指令可以引用,只有invokespecial指令(§invokespecial)可以引用。* 6 | 7 | -------------------------------------------------------------------------------- /4-The_class_File_Format/4.2_Names/4.2.3_Module_and_Package_Names.md: -------------------------------------------------------------------------------- 1 | Module的名字引用自储存在常量池([§4.4.11](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.11))中CONSTANT_Module_info结构的Module属性中。由CONSTANT_Module_info结构中的CONSTANT_Utf8_info指出该module的名字。模块名称与类和接口名称不同,不以“内部形式”编码,即,用于分隔模块名称中的标识符的ASCII句点(.)不会被ASCII正斜杠(/)替换。 2 | 3 | 模块名称可以采用任何由Unicode编码的字符,但受以下约束条件限制: 4 | 5 | - 模块名称不得包含“\ u0000”到“\ u001F”范围内的任何代码点。 6 | - ASCII反斜杠(\)为保留字符,用于在模块名称中做转义。他仅可以出现在冒号(:),at符号(@)或反斜杠(/)前。ASCII字符序列(\\\) 可用于编码模块名称中的反斜杠。 7 | - ASCII冒号(:)和at符号(@)保留供将来在模块名称中使用。他们只有被转义后才可以出现先module名字中。ASCII字符序列\:和\ @可用于对模块名称中的冒号和符号进行编码。 8 | 9 | 从Module属性引用的package名称存储在常量池([§4.4.12](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.12))中的CONSTANT_Package_info结构中。由CONSTANT_Package_info结构包装CONSTANT_Utf8_info结构,该结构以内部形式编码。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.3_Descriptors/4.3.1_Grammar_Notation.md: -------------------------------------------------------------------------------- 1 | 描述符局有特定的语法规范。语法是一组用于规范字符序列如何形成各种合法的描述符的产品。语法的终端符号以固定宽度字体显示。非终端符号以斜体显示。非终端符的定义由被定义的非终端符后跟冒号的名称显示。然后,对于非终端符的一个或多个替代定义遵循以下规范。 2 | 3 | 右侧的符号{x}表示零次或多次出现x。 4 | 5 | 位于右侧的短语(one of)表示下一行或多行上的每个终端符号另外一种替代定义。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.3_Descriptors/4.3.2_Field_Descriptors.md: -------------------------------------------------------------------------------- 1 | 属性描述符中包含了类,实例和局部变量的相关类型。 2 | 3 | > FieldDescriptor: 4 | > 5 | > [FieldType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-FieldType) 6 | > 7 | > FieldType: 8 | > 9 | > [BaseType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-BaseType) 10 | > [ObjectType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-ObjectType) 11 | > [ArrayType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-ArrayType) 12 | > 13 | > BaseType: 14 | > 15 | > (one of) 16 | > `B` `C` `D` `F` `I` `J` `S` `Z` 17 | > 18 | > ObjectType: 19 | > 20 | > ``` 21 | > L` ClassName `; 22 | > ``` 23 | > 24 | > ArrayType: 25 | > 26 | > `[` [ComponentType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-ComponentType) 27 | > 28 | > ComponentType: 29 | > 30 | > [FieldType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-FieldType) 31 | 32 | BaseType的字符,ObjectType中的L和;,ArrayType中的]都是ASCII字符。 33 | 34 | ClassName以内部形式编码表示二进制类或接口名称([§4.2.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.2.1))。 35 | 36 | 字段描述符类型的解释如表[Table 4.3-A](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.3.2-200).所示。 37 | 38 | 表示数组类型的字段描述符仅在表示具有255或更少维度的类型时才有效。 39 | 40 | **Table 4.3-A. Interpretation of field descriptors** 41 | 42 | | *FieldType* term | Type | Interpretation | 43 | | ------------------- | ----------- | ------------------------------------------------------------ | 44 | | `B` | `byte` | signed byte | 45 | | `C` | `char` | Unicode character code point in the Basic Multilingual Plane, encoded with UTF-16 | 46 | | `D` | `double` | double-precision floating-point value | 47 | | `F` | `float` | single-precision floating-point value | 48 | | `I` | `int` | integer | 49 | | `J` | `long` | long integer | 50 | | `L` *ClassName* `;` | `reference` | an instance of class *ClassName* | 51 | | `S` | `short` | signed short | 52 | | `Z` | `boolean` | `true` or `false` | 53 | | `[` | `reference` | one array dimension | 54 | 55 | > int类型的实例变量的字段描述符就是I. 56 | > 57 | > Object类型的实例变量的字段描述符是Ljava / lang / Object;。请注意,使用类Object的二进制名称的内部形式。 58 | > 59 | > 多维数组类型double [] [] []的实例变量的字段描述符是[[[D. -------------------------------------------------------------------------------- /4-The_class_File_Format/4.3_Descriptors/4.3.3_Method_Descriptors.md: -------------------------------------------------------------------------------- 1 | 一个方法描述符包含了零个或多个参数描述符和一个返回值描述符。他们分别指出了该方法接收的参数类型和返回类型(如果有的话)。 2 | 3 | > MethodDescriptor: 4 | > 5 | > `(` {[ParameterDescriptor](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-ParameterDescriptor)} `)` [ReturnDescriptor](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-ReturnDescriptor) 6 | > 7 | > ParameterDescriptor: 8 | > 9 | > [FieldType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-FieldType) 10 | > 11 | > ReturnDescriptor: 12 | > 13 | > [FieldType](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-FieldType) 14 | > [VoidDescriptor](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-VoidDescriptor) 15 | > 16 | > VoidDescriptor: 17 | > 18 | > V 19 | 20 | 其中,字母V表示该方法没有返回值(即void) 21 | 22 | > The method descriptor for the method: 23 | > 24 | > ``` 25 | > Object m(int i, double d, Thread t) {...} 26 | > ``` 27 | > 28 | > is: 29 | > 30 | > ``` 31 | > (IDLjava/lang/Thread;)Ljava/lang/Object; 32 | > ``` 33 | > 34 | > Note that the internal forms of the binary names of `Thread` and `Object` are used. 35 | 36 | 方法描述符中的参数总长度应小于255,其中对实例接口方法调用时传入的this指针长度也包含在内。其总长度是每一个参数长度的和。其中long和double占用两个单位长度,其他类型占用一个单位长度。 37 | 38 | 对于类方法和接口方法来说,他们的方法描述符都是一致的。尽管实例方法在被调用时需将this引用作为一个附加参数传递进去,但是这个并没有体现在方法描述符中。实例方法中this引用的传递由Java虚拟机指令隐式生成([§2.6.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6.1), [§4.11](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.11))。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.3_Descriptors/Descriptors.md: -------------------------------------------------------------------------------- 1 | 用来表示类型,属性或方法的字符串被称为描述符。描述符在类文件格式中,使用被修改过的UTF-8字符串([§4.4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.7))编码,因此其可以使用Unicode进行绘制而不受任何约束。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.4_The_Constant_Pool/4.4.1_The_CONSTANT_Class_info_Structure.md: -------------------------------------------------------------------------------- 1 | 结构CONSTANT_Class_info用于表示类或接口 2 | 3 | ```c 4 | CONSTANT_Class_info { 5 | u1 tag; 6 | u2 name_index; 7 | } 8 | ``` 9 | 10 | 其元素如下: 11 | 12 | tag 13 | 14 | ​ tag项的值为CONSTANT_Class(7)。 15 | 16 | name_index 17 | 18 | ​ name_index的值应为constant_pool中的一个有效索引。其索引处应为表现了类或接口的内部CONSTANT_Utf8_info结构([§4.4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.7)) 。 19 | 20 | 因为数组也属于对象,所以对应的操作码为anewarray和multianewarray-而不是new操作码-可以通过constant_pool表中的CONSTANT_Class_info结构引用数组“类”。对于此类数组类,其名称为数组类型的描述符([§4.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.3.2))。 21 | 22 | > 例如,表示二维数组类型int [] []的类名是[[I],而表示类型Thread []的类名是[Ljava / lang / Thread; 23 | 24 | 数组类型描述符仅在表示数组维度为255以下时才有效。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.4_The_Constant_Pool/4.4.2_The_CONSTANT_Fieldref_info_CONSTANT_Methodref_info_and_CONSTANT_InterfaceMethodref_info_Structures.md: -------------------------------------------------------------------------------- 1 | 字段,方法和接口方法由相似的结构表示: 2 | 3 | ```c 4 | CONSTANT_Fieldref_info { 5 | u1 tag; 6 | u2 class_index; 7 | u2 name_and_type_index; 8 | } 9 | 10 | CONSTANT_Methodref_info { 11 | u1 tag; 12 | u2 class_index; 13 | u2 name_and_type_index; 14 | } 15 | 16 | CONSTANT_InterfaceMethodref_info { 17 | u1 tag; 18 | u2 class_index; 19 | u2 name_and_type_index; 20 | } 21 | ``` 22 | 23 | 这些结构的属性如下: 24 | 25 | **tag** 26 | 27 | ​ CONSTANT_Fieldref_info结构的标签项的值为CONSTANT_Fieldref(9)。 28 | 29 | ​ CONSTANT_Methodref_info结构的标签项的值为CONSTANT_Methodref(10)。 30 | 31 | ​ CONSTANT_InterfaceMethodref_info结构的标签项的值为CONSTANT_InterfaceMethodref(11)。 32 | 33 | **class_index** 34 | 35 | ​ class_index项目的值必须是constant_pool表中的有效索引。该索引处的constant_pool条目必须是CONSTANT_Class_info结构 ([§4.4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.1)),该结构表示将字段或方法作为成员的类或接口类型。 36 | 37 | ​ 在CONSTANT_Fieldref_info结构中,class_index项可以是类类型,也可以是接口类型。 38 | 39 | ​ 在CONSTANT_Methodref_info结构中,class_index项必须是类类型,而不是接口类型。 40 | 41 | ​ 在CONSTANT_InterfaceMethodref_info结构中,class_index项必须是接口类型,而不是类类型。 42 | 43 | **name_and_type_index** 44 | 45 | ​ name_and_type_index项目的值必须是指向constant_pool表的有效索引。该索引处的constant_pool条目必须是CONSTANT_NameAndType_info结构([§4.4.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.6))。此constant_pool条目指示字段或方法的名称和描述符。 46 | 47 | ​ 在CONSTANT_Fieldref_info结构中,指示的描述符必须是字段描述符 ([§4.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.3.2))。否则,指示的描述符必须是方法描述符([§4.3.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.3.3))。 48 | 49 | ​ 如果CONSTANT_Methodref_info结构中方法的名称以'<'('\ u003c')开头,则该名称必须为特殊名称,代表实例初始化方法([§2.9.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.9.1))。这种方法的返回类型必须为空。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.4_The_Constant_Pool/4.4.3_The_CONSTANT_String_info_Structure.md: -------------------------------------------------------------------------------- 1 | CONSTANT_String_info结构用于表示String类型的常量对象: 2 | 3 | ```c 4 | CONSTANT_String_info { 5 | u1 tag; 6 | u2 string_index; 7 | } 8 | ``` 9 | 10 | CONSTANT_String_info结构的各项如下: 11 | 12 | tag 13 | 14 | ​ 标签项的值为CONSTANT_String(8)。 15 | 16 | string_index 17 | 18 | ​ string_index项目的值必须是指向constant_pool表的有效索引。该索引处的constant_pool条目必须是CONSTANT_Utf8_info结构([§4.4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.7)) ,该结构表示要初始化String对象的Unicode代码点的序列。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.4_The_Constant_Pool/4.4.4_The_CONSTANT_Integer_info_and_CONSTANT_Float_info_Stuctures.md: -------------------------------------------------------------------------------- 1 | CONSTANT_Integer_info和CONSTANT_Float_info结构表示4字节的数字常量(int和float); 2 | 3 | ```c 4 | CONSTANT_Integer_info { 5 | u1 tag; 6 | u4 bytes; 7 | } 8 | 9 | CONSTANT_Float_info { 10 | u1 tag; 11 | u4 bytes; 12 | } 13 | ``` 14 | 15 | 该结构的项目如下: 16 | 17 | **tag** 18 | 19 | ​ CONSTANT_Integer_info结构的标签项的值为CONSTANT_Integer(3)。 20 | 21 | ​ CONSTANT_Float_info结构的标签项的值为CONSTANT_Float(4)。 22 | 23 | **bytes** 24 | 25 | ​ CONSTANT_Integer_info结构的bytes项表示int常量的值。该值的字节以大端(高字节在前)顺序存储。 26 | 27 | ​ CONSTANT_Float_info结构的字节项目表示IEEE 754浮点单格式([§2.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.3.2))中的float常数的值。单一格式表示形式的字节以big-endian(高字节在前)顺序存储。 28 | 29 | ​ 由CONSTANT_Float_info结构表示的值如下确定。该值的字节首先转换为int常量位。然后: 30 | 31 | - 如果bits为0x7f800000,则float值将为正无穷大。 32 | 33 | - 如果bits为0xff800000,则float值将为负无穷大。 34 | 35 | - 如果bit的值为0x7FFFFFFF到0xffffffff之间,或0xff800001到0x7f800001之间,则该浮点值为NaN。 36 | 37 | - 在所有其他情况下,根据bit计算s,e和m为三个值: 38 | 39 | - ```c 40 | int s = ((bits >> 31) == 0) ? 1 : -1; 41 | int e = ((bits >> 23) & 0xff); 42 | int m = (e == 0) ? 43 | (bits & 0x7fffff) << 1 : 44 | (bits & 0x7fffff) | 0x800000; 45 | ``` 46 | 47 | 然后浮点值等于数学表达式s·m·2e-150的结果。 -------------------------------------------------------------------------------- /4-The_class_File_Format/4.4_The_Constant_Pool/The_Constant_Pool.md: -------------------------------------------------------------------------------- 1 | Java虚拟机指令不依赖于类,接口,类实例或数组的运行时布局。相反,JVM指令依赖的是constant_pool表中的符号信息。 2 | 3 | 所有的常量元素都为以下格式: 4 | 5 | ```c 6 | cp_info { 7 | u1 tag; 8 | u1 info[]; 9 | } 10 | ``` 11 | 12 | constant_pool表中的每个条目必须以1字节标记开头,表示条目的常量类型。表[Table 4.4-A](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4-140)按章节顺序列出了17种常量及其对应的标记。每个标记字节后面必须跟有两个或多个字节,提供有关该常量的信息。其附加信息的格式取决于不同的tag标记字节。也就是说,info数组的内容随tag的值而变化。 13 | 14 | **Table 4.4-A. Constant pool tags (by section)** 15 | 16 | | Constant Kind | Tag | Section | 17 | | ----------------------------- | ---- | ------------------------------------------------------------ | 18 | | `CONSTANT_Class` | 7 | [§4.4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.1) | 19 | | `CONSTANT_Fieldref` | 9 | [§4.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.2) | 20 | | `CONSTANT_Methodref` | 10 | [§4.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.2) | 21 | | `CONSTANT_InterfaceMethodref` | 11 | [§4.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.2) | 22 | | `CONSTANT_String` | 8 | [§4.4.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.3) | 23 | | `CONSTANT_Integer` | 3 | [§4.4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.4) | 24 | | `CONSTANT_Float` | 4 | [§4.4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.4) | 25 | | `CONSTANT_Long` | 5 | [§4.4.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.5) | 26 | | `CONSTANT_Double` | 6 | [§4.4.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.5) | 27 | | `CONSTANT_NameAndType` | 12 | [§4.4.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.6) | 28 | | `CONSTANT_Utf8` | 1 | [§4.4.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.7) | 29 | | `CONSTANT_MethodHandle` | 15 | [§4.4.8](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.8) | 30 | | `CONSTANT_MethodType` | 16 | [§4.4.9](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.9) | 31 | | `CONSTANT_Dynamic` | 17 | [§4.4.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.10) | 32 | | `CONSTANT_InvokeDynamic` | 18 | [§4.4.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.10) | 33 | | `CONSTANT_Module` | 19 | [§4.4.11](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.11) | 34 | | `CONSTANT_Package` | 20 | [§4.4.12](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.12) | 35 | 36 | 在版本号为v的类文件中,constant_pool表中所出现的tag值必须是首次在类文件格式 ([§4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1))版本v或更早版本中定义的标记。也就是说,每个条目必须表示一种被批准在类文件中使用的常量。表 [Table 4.4-B](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4-210) 列出了每个标记,以及定义它的类文件格式的第一个版本。 37 | 38 | **Table 4.4-B. Constant pool tags (by tag)** 39 | 40 | | Constant Kind | Tag | `class` file format | Java SE | 41 | | ----------------------------- | ---- | ------------------- | ------- | 42 | | `CONSTANT_Utf8` | 1 | 45.3 | 1.0.2 | 43 | | `CONSTANT_Integer` | 3 | 45.3 | 1.0.2 | 44 | | `CONSTANT_Float` | 4 | 45.3 | 1.0.2 | 45 | | `CONSTANT_Long` | 5 | 45.3 | 1.0.2 | 46 | | `CONSTANT_Double` | 6 | 45.3 | 1.0.2 | 47 | | `CONSTANT_Class` | 7 | 45.3 | 1.0.2 | 48 | | `CONSTANT_String` | 8 | 45.3 | 1.0.2 | 49 | | `CONSTANT_Fieldref` | 9 | 45.3 | 1.0.2 | 50 | | `CONSTANT_Methodref` | 10 | 45.3 | 1.0.2 | 51 | | `CONSTANT_InterfaceMethodref` | 11 | 45.3 | 1.0.2 | 52 | | `CONSTANT_NameAndType` | 12 | 45.3 | 1.0.2 | 53 | | `CONSTANT_MethodHandle` | 15 | 51.0 | 7 | 54 | | `CONSTANT_MethodType` | 16 | 51.0 | 7 | 55 | | `CONSTANT_Dynamic` | 17 | 55.0 | 11 | 56 | | `CONSTANT_InvokeDynamic` | 18 | 51.0 | 7 | 57 | | `CONSTANT_Module` | 19 | 53.0 | 9 | 58 | | `CONSTANT_Package` | 20 | 53.0 | 9 | 59 | 60 | constant_pool表中的某些条目是可加载的,因为他们可以在运行时压入堆栈以供进一步计算使用。在版本号为v的类文件中,如果constant_pool表中的条目为首次被认为可在版本v或更早版本中加载的标记,则该条目是可加载的。表 [Table 4.4-C](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4-310) 列出了每个标记首个被认为是可加载的Java SE版本。还显示了Java SE引入了该类文件格式的版本。 61 | 62 | *在除CONSTANT_Class之外的情况下,首个定义该标签的类文件格式于首个可加载该标签的Java SE为同一个版本。* 63 | 64 | **Table 4.4-C. Loadable constant pool tags** 65 | 66 | | Constant Kind | Tag | `class` file format | Java SE | 67 | | ----------------------- | ---- | ------------------- | ------- | 68 | | `CONSTANT_Integer` | 3 | 45.3 | 1.0.2 | 69 | | `CONSTANT_Float` | 4 | 45.3 | 1.0.2 | 70 | | `CONSTANT_Long` | 5 | 45.3 | 1.0.2 | 71 | | `CONSTANT_Double` | 6 | 45.3 | 1.0.2 | 72 | | `CONSTANT_Class` | 7 | 49.0 | 5.0 | 73 | | `CONSTANT_String` | 8 | 45.3 | 1.0.2 | 74 | | `CONSTANT_MethodHandle` | 15 | 51.0 | 7 | 75 | | `CONSTANT_MethodType` | 16 | 51.0 | 7 | 76 | | `CONSTANT_Dynamic` | 17 | 55.0 | 11 | 77 | 78 | -------------------------------------------------------------------------------- /4-The_class_File_Format/The_class_File_Format.md: -------------------------------------------------------------------------------- 1 | 本章讲述虚拟机中class文件的格式。每个class文件都包含类,接口或模块的定义。虽然类,接口或模块不需要在文件中存在明确的表示(例如,因为类是由类加载器生成的),但我们通常将将类,接口或模块的任何有效表示称为类文件格式。 2 | 3 | 类文件由8位字节流组成。16位和32位量分别通过读取两个和四个连续的8位字节来构造。多字节数据项始终以big-endian顺序存储(高位字节在前)。本章定义数据类型u1,u2和u4,分别表示无符号一字节,两字节或四个字节类型。 4 | 5 | 在Java SE Platform API中,由java.io.DataInput和java.io.DataOutput以及java.io.DataInputStream和java.io.DataOutputStream等类支持类文件格式。例如,类型u1,u2和u4的值可以通过诸如接口java.io.DataInput的readUnsignedByte,readUnsignedShort和readInt之类的方法来读取。 6 | 7 | 本章将使用类似C语言编写的伪代码表示类文件格式。为避免与类和类实例等字段混淆,描述类文件格式中结构的内容统一称为项。其按顺序存储在类文件中,无需填充或对齐。 8 | 9 | 类文件中,包含了零个或多个项的结构称为表,尽管我们使用了类似C的语法来引用表项,事实上,不同大小的表结构流意味着不可能将表索引直接转换为表中的字节偏移量。 10 | 11 | 数组是由零个或多个连续的固定大小的项组成,可以像通过索引去访问数据内容。 12 | 13 | 本章中对ASCII字符的引用应解释为与ASCII字符对应的Unicode点。 -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.1_The_Run-Time_Constant_Pool.md: -------------------------------------------------------------------------------- 1 | JVM为每个类或接口都维护了一个运行时常量池 ([§2.5.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.5.5))。该数据结构服务于常规编程语言实现的符号表的许多目的(*This data structure serves many of the purposes of the symbol table of a conventional programming language implementation*)。类或接口的二进制表示形式中的*constant_pool*表([§4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4)) 用于在类或接口创建时构造运行时常量池([§5.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3))。 2 | 3 | 运行时常量池中有两种数据:符号引用(在 [§5.4.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3)中会讲到),和无需进一步处理的静态常量。 4 | 5 | 运行时常量池中的符号引用是根据*constant_pool*表中每个条目的结构数据生成的: 6 | 7 | - 对类或接口的符号引用是根据CONSTANT_Class_info结构([§4.4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.1))生成的。一个引用会以下列形式给出了类或接口的名称: 8 | 9 | - 对于非数组类型的类或接口,他的名字就是其class或interface二进制给出的名字 ([§4.2.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.2.1))。 10 | - 对于一个由N阶的数组来说,名称以n个ASCII字符'['后跟元素类型来表示: 11 | - 如果元素类型是基本类型,则它由相应的字段描述符 ([§4.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.3.2))表示。 12 | - 否则,如果元素你引用类型,名称以ASCII字符'L'后跟元素类型的二进制名称,并加上ASCII字符';'。 13 | 14 | 每当本章引用类或接口的名称时,该名称应理解为上述形式(这也是Class.getName方法返回的)。 15 | 16 | - 对类或接口的字段的符号引用是根据CONSTANT_Fieldref_info结构生成的 ([§4.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.2))。该引用给出了字段的名称和描述符,以及对其所在class或interface的引用。 17 | - 对类的方法的符号引用是根据CONSTANT_Methodref_info结构 ([§4.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.2))生成的。该引用中给出了方法的名称和描述符,以及对其所在class或interface的引用。 18 | - 对接口方法的符号引用是根据CONSTANT_InterfaceMethodref_info结构 ([§4.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.2))生成的。该引用给出了接口方法的名称和描述符,以及对其所在接口的引用。 19 | - 方法句柄的符号引用是根据CONSTANT_MethodHandle_info结构([§4.4.8](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.8))生成的。该引用给出了接口或类中的字段,或类中的方法,或接口中的方法,其取决于方法句柄的类型。 20 | - 方法类型的符号引用派生自CONSTANT_MethodType_info结构 ([§4.4.9](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.9))。这样的引用给出了方法描述符 ([§4.3.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.3.3))。 21 | - *dynamically-computed constant*的符号引用是从CONSTANT_Dynamic_info结构(第4.4.10节)派生的。这样的引用给出: 22 | - 对方法句柄的符号引用,将调用它来计算常量的值; 23 | - 一系列符号引用和静态常量,在调用方法句柄时将用作静态参数; 24 | - 不合格的名称和字段描述符。 25 | - 对 *dynamically-computed*的调用位置的符号引用是从CONSTANT_InvokeDynamic_info结构 ([§4.4.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.10))派生的。这样的引用给出: 26 | - 对方法句柄的符号引用,它将在invokedynamic指令 ([§*invokedynamic*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.invokedynamic)) 的过程中调用,以计算java.lang.invoke.CallSite的实例; 27 | - 一系列符号引用和静态常量,在调用方法句柄时将用作静态参数; 28 | - 不合格的名称和方法描述符。 29 | 30 | 运行时常量池中的静态常量也是根据每个条目的结构根据constant_pool表中的条目派生的: 31 | 32 | - 字符串常量是对String类实例的引用,它是从CONSTANT_String_info结构派生的([§4.4.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.3))。为了派生字符串常量,Java虚拟机会检查CONSTANT_String_info结构给出的代码点序列: 33 | 34 | - 如果之前在String类的实例上调用了String.intern方法,该类包含与CONSTANT_String_info结构给出的Unicode代码点序列相同的Unicode代码点序列,然后,字符串常量是对String的同一实例的引用。 35 | - 否则,将创建一个类String的新实例,其中包含CONSTANT_String_info结构给出的Unicode代码点序列。字符串常量是对新实例的引用。最后,在新实例上调用String.intern方法。 36 | 37 | - 数字常量派生自CONSTANT_Integer_info,CONSTANT_Float_info,CONSTANT_Long_info和CONSTANT_Double_info结构([§4.4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.4), [§4.4.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4.5))。 38 | 39 | 请注意,CONSTANT_Float_info结构表示IEEE 754单精度的值,CONSTANT_Double_info结构表示IEEE 754双精度的值。因此,从这些结构导出的数值常数必须是可以分别使用IEEE 754单精度和双精度表示的值。 40 | 41 | constant_pool表中的其余结构 - 描述性结构CONSTANT_NameAndType_info,CONSTANT_Module_info和CONSTANT_Package_info以及基础结构CONSTANT_Utf8_info - 仅在构造运行时常量池时间接使用。运行时常量池中的条目不直接对应于这些结构。 42 | 43 | 运行时常量池中的某些条目是可加载的,这意味着: 44 | 45 | - 它们可以通过ldc指令系列 ([§*ldc*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.ldc), [§*ldc_w*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.ldc_w), [§*ldc2_w*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.ldc2_w))压入堆栈。 46 | - 它们可能是动态计算常量和调用位置的引导方法的静态参数([§5.4.3.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3.6))。 47 | 48 | 如果运行时常量池中的数据项是从可加载的constant_pool表中的项派生的,则该项也是可加载的( [Table 4.4-C](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4-310)): 49 | 50 | - 对类和接口的符号引用 51 | - 对方法句柄的符号引用 52 | - 对方法类型的符号引用 53 | - 对动态计算常量的符号引用 54 | - 静态常量 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.2_Java_Virtual_Machine_Startup.md: -------------------------------------------------------------------------------- 1 | Java虚拟机通过使用引导类加载器([§5.3.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.1))或用户定义的类加载器([§5.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.2)).创建初始类或接口来启动。然后,Java虚拟机链接初始类或接口,对其进行初始化,并调用公共静态方法*void main(String [])*。调用此方法会驱动其进一步的执行。构造main方法的Java虚拟机指令的执行可能导致附加类和接口的链接(并因此创建),以及其他方法的调用。 -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.3_Creation_and_Loading/5.3.1_LoadingUsing_the_Bootstrap_class_Loader.md: -------------------------------------------------------------------------------- 1 | 以下步骤用于使用引导类加载器加载并由此创建由N表示的非数组类或接口C。 2 | 3 | 首先,Java虚拟机确定引导类加载器是否已加载由N表示的类或接口。如果是的话,已有类或接口C,并且无需创建类。 4 | 5 | 否则,Java虚拟机将N传递给引导类加载器上的方法的调用,以平台相关的方式搜索C的表示。通常,类或接口将使用分层文件系统中的文件表示,类或接口的名称将被编码在文件的路径名中。 6 | 7 | 请注意,不能保证以上表示形式为C合法的表示形式。此加载阶段必须检测以下错误: 8 | 9 | **如果找不到对应的C表示形式,则加载将引发ClassNotFoundException的实例。** 10 | 11 | 然后,Java虚拟机将尝试使用引导类加载器,使用 [§5.3.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.5)中的算法,从定义的表示中创建由N表示的类。得到C. -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.3_Creation_and_Loading/5.3.2_Loading_Using_a_User_defined_Class_loader.md: -------------------------------------------------------------------------------- 1 | 以下步骤将使用一个用户定义的类加载器L用来加载一个由N表示的非数组类C。 2 | 3 | 首先,Java虚拟机确定L是否已记录N类或接口初始化。如果有的话,无序重复创建C类。 4 | 5 | 否则,jvm会调用L的loadClass方法,将N做为参数。该方法的返回时已创建好的类C。然后,jvm会记录加载器L为类C的初始加载器([§5.3.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.4))。本节的其余部分将更详细地描述此过程。 6 | 7 | 当使用要加载的类或接口C的名称N调用类加载器L的loadClass方法时,L必须执行以下两个操作之一才能加载C: 8 | 9 | 1. 类加载器L可以创建一个字节数组,使用ClassFile结构的字节来表示C ([§4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1));然后,它必须调用ClassLoader类的defineClass方法。调用defineClass会导致Java虚拟机使用 [§5.3.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.5)中的算法,从字节数组中使用L派生N表示的类或接口。 10 | 2. 类加载器L可以将C的加载委托给其他一些类加载器L'。这是通过将参数N直接或间接传递给L'上的方法调用(通常是loadClass方法)来实现的。调用的返回为C。 11 | 12 | **在(1)或(2)中,如果类加载器L由于任何原因而无法加载由N表示的类或接口,则它必须抛出ClassNotFoundException的实例。** 13 | 14 | *从JDK 1.1开始,Oracle的Java虚拟机实现调用了类加载器的loadClass方法,以使其加载类或接口。loadClass的参数是要加载的类或接口的名称。还有一个loadClass方法的两个参数版本,其中第二个参数是一个布尔值,指示是否要链接该类或接口。JDK 1.0.2中仅提供了两个参数的版本,并且Oracle的Java虚拟机实现依靠它来链接已加载的类或接口。从JDK 1.1开始,Oracle的Java虚拟机实现直接链接类或接口,而无需依赖类加载器。* -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.3_Creation_and_Loading/5.3.3_Creating_Array_Classes.md: -------------------------------------------------------------------------------- 1 | 以下步骤用于使用类加载器L创建由N表示的数组类C。类加载器L可以是引导类加载器,也可以是用户定义的类加载器。 2 | 3 | 如果L已被记录为与N具有相同组件类型的数组类的启动加载器,则该类为C,并且不需要创建数组类。 4 | 5 | 否则,执行以下步骤来创建C: 6 | 7 | 1. 如果组件类型是引用类型,则使用类加载器L递归应用本节 ([§5.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3)) 的算法,以便加载并由此创建C的组件类型。 8 | 9 | 2. Java虚拟机使用指定的组件类型和维数创建一个新的数组类。 10 | 11 | 如果组件类型是引用类型,则将C标记为已由组件类型的定义类加载器定义,否则,C被标记为由引导类加载器定义。 12 | 13 | 在任何情况下,Java虚拟机都将记录L是C的启动加载器 ([§5.3.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.4))。 14 | 15 | 如果组件类型是引用类型,则数组类的可访问性由其组件类型的可访问性确定([§5.4.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.4))。否则,所有类和接口都可以访问数组类。 16 | 17 | -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.3_Creation_and_Loading/5.3.4_Loading_Constraints.md: -------------------------------------------------------------------------------- 1 | 为了保证类型安全,与类加载器关联时需要特别注意。当两个不同的类加载器初始化类N时,N在每个加载器中可能表示不同类或接口。 2 | 3 | 当类或接口C = 1,L1>对另一个类D = 2,L2>的字段或方法进行符号引用时,符号引用包含一个描述符,用于指定字段的类型或方法的返回值和参数类型。至关重要的是,在字段或方法描述符中提到的可以为任何类型N在由L1加载和由L2加载时都表示相同的类或接口。 4 | 5 | **为了确保这一点,Java虚拟机在准备([§5.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.2)) 和解析 ([§5.4.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3))期间施加形式为NL1 = NL2 的加载约束。为了强制执行这些约束,Java虚拟机将在某些规定的时间(请参阅 [§5.3.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.1), [§5.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.2), [§5.3.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.3), 和 [§5.3.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.5))记录特定的加载程序是特定类的启动加载程序。记录加载程序是类的初始加载程序后,Java虚拟机必须立即检查是否违反了任何加载约束。如果是这样,记录将被撤消,Java虚拟机将引发LinkageError,并且加载操作将失败。** 6 | 7 | **同样,在施加加载约束后(请参见 [§5.4.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.2), [§5.4.3.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3.2), [§5.4.3.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3.3), 和[§5.4.3.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3.4)),Java虚拟机必须立即检查是否违反了任何加载约束。如果是这样,则新施加的加载约束将被撤消,Java虚拟机将引发LinkageError,并且导致施加约束的操作(视情况而定,可能是解决方案或准备工作)失败。** 8 | 9 | 这里描述的情况是Java虚拟机检查是否违反任何加载约束的唯一时间。仅当以下四个条件均成立时,才会违反加载约束: 10 | 11 | - 存在一个加载程序L,使得Java虚拟机已将L记录为名为N的类C的启动加载程序。 12 | - 存在一个加载程序L',这样Java虚拟机已将L'记录为名为N的类C'的启动加载程序。 13 | - 由(强制传递的)约束集合定义的等价关系表示NL = NL'。 14 | - C ≠ C '. 15 | 16 | *关于类装载器和类型安全性的完整讨论不在本规范的范围之内。要进行更全面的讨论,请参阅Sheng Liang和Gilad Bracha撰写的Java虚拟机中的动态类加载(1998年ACM SIGPLAN面向对象编程系统,语言和应用程序会议的论文集)。* -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.3_Creation_and_Loading/5.3.5_Deriving_a_Class_from_a_class_File_Representation.md: -------------------------------------------------------------------------------- 1 | 以下几个步骤使用加载器L将一个非数组类型的类文件N派生出一个Class对象C。 2 | 3 | 1. **首先,jvm需确认加载器L没有记录过类N。如果有的话,该创建过程是非法的,会抛出LinkageError。** 4 | 5 | 2. 否则,jvm会尝试加载该类。但是,该文件实际上可能不是C的有效表现形式。 6 | 7 | 此加载阶段必须检测以下错误: 8 | 9 | - **如果类文件表示形式不是ClassFile结构([§4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1), [§4.8](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.8)),则加载将引发ClassFormatError错误。** 10 | 11 | - **否则,如果表示形式的major version和minor version([§4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.1))不是受支持的版本,会抛出UnsupportedClassVersionError。** 12 | 13 | *引入了UnsupportedClassVersionError,它是ClassFormatError的子类,可以轻松识别由尝试加载其表示使用不支持的类文件格式版本的类引起的ClassFormatError。在JDK 1.1和更早版本中,如果版本不受支持,则抛出NoClassDefFoundError或ClassFormatError实例,具体取决于该类是由系统类加载器加载还是由用户定义的类加载器加载。* 14 | 15 | - **否则,如果表现形式实际上并不是类N,加载过程会抛出NoClassDefFoundError或其子类的实例。当声称的表示形式具有this_class项(其指定的名称不是N)或access_flags项(其设置了ACC_MODULE标志)时,就会发生这种情况。** 16 | 17 | 3. 如果C有直接父类,使用 [§5.4.3.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3.1)的算法解析从C到其直接超类的符号引用。请注意,如果C是接口,则它必须具有Object作为其直接超类,并且必须已经加载了它。只有Object没有直接的超类。 18 | 19 | **此加载阶段的结果是,由于类或接口解析而可能引发的任何异常都可以引发。此外,此加载阶段必须检测以下错误:** 20 | 21 | - **如果实际上命名为C的直接超类的类或接口是接口,则加载会引发IncompatibleClassChangeError。** 22 | - **否则,如果C的任何超类都是C本身,则加载将引发ClassCircularityError。** 23 | 24 | 4. 如果C具有任何直接超接口,则使用[§5.4.3.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3.1)的算法解析从C对其直接超接口的符号引用。 25 | 26 | **此加载阶段的结果是,由于类或接口解析而可能引发的任何异常都可以引发。此外,此加载阶段必须检测以下错误:** 27 | 28 | - **如果任何命名为C的直接超接口的类或接口实际上都不是接口,则加载会引发IncompatibleClassChangeError。** 29 | - 否则,如果C的任何超接口是C本身,则加载将引发ClassCircularityError。 30 | 31 | 5. Java虚拟机将C标记为具有L作为其定义类加载器,并记录L是C的初始加载器([§5.3.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.4))。 -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.3_Creation_and_Loading/Creation_and_Loading.md: -------------------------------------------------------------------------------- 1 | 使用位于虚拟机的方法区([§2.5.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.5.4)) 中的构造方法创建由N表示的类或接口C特定于实现的内部实现。类的创建可以被其他的类触发,例如被在运行时常量池中引用到C的类D。在D类中间接的调用C的方法也可以触发C的创建,例如反射([§2.12](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.12)) 。 2 | 3 | 如果C不为数组类,通过被类加载器加载其二进制表示所创建([§4 (*The `class` File Format*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html))。数组类没有外部的二进制形式;它们是由Java虚拟机而不是由类加载器创建的。 4 | 5 | 类加载器分为两种:jvm提供的启动类加载器和用户定义的类加载器。没一个用户定义的类加载器都是抽象类ClassLoader的子类。应用程序使用用户定义的类加载器,以扩展Java虚拟机动态加载并由此创建类的方式。用户定义的类加载器可用于创建源自用户定义的源的类。例如,可以通过网络下载类,动态生成类或从加密文件中提取类。 6 | 7 | 类加载器L可以通过直接定义C或委派给另一个类加载器来创建C。如果L直接创建C,我们说L定义了C,或者说L是C的定义加载器。 8 | 9 | 当一个类加载器委托给另一个类加载器时,启动加载过程的加载器不必与完成加载并定义类的加载器相同。如果L创建了C,无论其直径创建还是委托,我们认为L启动了C的加载,或者等效地,L是C的启动加载器。 10 | 11 | 在运行时,类或接口不是仅由其名称确定的,而成对使用:其二进制名称 ([§4.2.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.2.1)) 及其定义的类加载器。每个此类或接口都属于一个运行时包。类或接口的运行时程序包由程序包名称和定义该类或接口的类加载器确定。 12 | 13 | Java虚拟机使用以下三个过程之一来创建由N表示的类或接口C: 14 | 15 | - 如果N表示非数组类或接口,则使用以下两种方法之一来加载并由此创建C: 16 | - 如果D由引导类加载器定义,则引导类加载器将启动C的加载 ([§5.3.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.1))。 17 | - 如果D是由用户定义的类加载器定义的,则该用户定义的类加载器将启动C的加载(第5.3.2节)。 18 | - 否则,为N数组类。数组类是直接由Java虚拟机 ([§5.3.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.3))而不是由类加载器创建的。但是,在创建数组类C的过程中会使用D的定义类加载器。 19 | 20 | **如果在类加载期间发生错误,则必须在程序中某个点(直接或间接)使用要加载的类或接口的位置上抛出LinkageError子类的实例。** 21 | 22 | **如果Java虚拟机曾经尝试在验证 ([§5.4.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.1)) 或解析([§5.4.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4.3))(而不是初始化 ([§5.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.5))期间加载类C,并且用于启动C加载的类加载器会抛出ClassNotFoundException的实例,那么Java虚拟机必须抛出NoClassDefFoundError实例,其原因是ClassNotFoundException实例。** 23 | 24 | **(这里的一个微妙之处是,作为解析的一部分执行了递归类加载以加载超类([§5.3.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3.5), 步骤3)。因此,由于类加载器无法加载超类而导致的ClassNotFoundException必须包装在NoClassDefFoundError中。)** 25 | 26 | 行为良好的类加载器应维护三个属性: 27 | 28 | - 给定相同的名称,好的类加载器应始终返回相同的Class对象。 29 | - 如果类加载器L1将类C的加载委托给另一个加载器L2,那么对于任何以C的直接超类或直接超接口出现的类型T,或作为C中字段的类型,或作为C中方法或构造函数的形式参数的类型,或作为C中方法的返回类型,L1和L2应该返回相同的Class对象。 30 | - 如果用户定义的类加载器预取了类和接口的二进制表示形式,或将一组相关的类一起加载,那么它必须仅在程序中不进行预取或组加载发生的点上反映加载错误。 31 | 32 | 我们有时会使用符号d>表示一个类或接口,其中N表示类或接口的名称,而Ld表示类或接口的定义加载程序。 33 | 34 | 我们还将使用符号NLi表示类或接口,其中N表示类或接口的名称,而Li表示类或接口的启动加载程序。 35 | 36 | -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/5.4_Linking/Linking.md: -------------------------------------------------------------------------------- 1 | 链接过程包含有验证和准备其直接超类,接口以及其类型(如果是数组的话)。链接过程还包括解析类中的符号引用,尽管验证和准备并不一定是同时发生的。 2 | 3 | 该规范允许jvm实现对链接活动(以及由于递归,加载)具有一定得灵活性,但前提是必须满足以下条件: 4 | 5 | - 类在链接时必须已经加载完成。 6 | 7 | - 类在初始化时必须已经完成了验证和准备阶段。 8 | 9 | - 链接期间检测到的错误会抛出到程序中某个位置,在该位置上,程序将采取某些操作,这些操作可能直接或间接地需要链接到错误所涉及的类或接口。 10 | 11 | - 直到(i)执行引用ldc,ldc_w或ldc2_w指令,或者(ii)调用将其作为静态参数引用的引导方法,才可以解析对动态计算常量的符号引用。 12 | 13 | 在调用将引用为静态参数的引导方法之前,不会解析对动态计算的call-site符号引用。 14 | 15 | 例如,Java虚拟机实现可以选择“懒汉式”链接策略,其中,使用类或接口中的每个符号引用(上面的符号引用除外)时,都将对其进行单独解析。或者,实现可以选择“饿汉式”链接策略,其中在验证类或接口时立即解析所有符号引用。这意味着在某些实现中,在初始化类或接口之后,解析过程可能会继续。无论采用哪种策略,在解析过程中检测到的任何错误都必须抛出在程序中直接或间接使用对类或接口的符号引用的某个点。 16 | 17 | **由于链接涉及分配新的数据结构,因此链接可能会失败,并抛出OutOfMemoryError。** -------------------------------------------------------------------------------- /5-Loading_Linking_and_Initializing/Loading_Linking_and_Initializing.md: -------------------------------------------------------------------------------- 1 | JVM动态加载,链接并初始化类和接口。Loading是查找具有特定名称的类或接口类型的二进制形式数据并从该二进制数据创建类或接口的过程。Linking是获取类或接口并将其组合到Java虚拟机的运行时状态以便可以执行的过程。类或接口的初始化(Initialization)包括执行类或接口初始化方法 ([§2.9.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.9.2))。 2 | 3 | 在本章中,[§5.1](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.1)描述了Java虚拟机如何将类或接口的二进制数据生成符号引用。 [§5.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.2) 讲述首次如何由Java虚拟机启动加载,链接和初始化的过程。 [§5.3](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.3)说明类加载器如何加载类和接口的二进制形式以及如何创建类和接口。链接在第 [§5.4](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.4)中描述。 [§5.5](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.5)详细说明了如何初始化类和接口。 [§5.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.6)介绍了绑定native方法的概念。最后,[§5.7](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-5.html#jvms-5.7)描述了Java虚拟机的退出。 -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/6.1_Assumptions_The_Meaning_of_Must.md: -------------------------------------------------------------------------------- 1 | 每条指令的描述总是基于满足 [§4 (*The class File Format*)](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html)中定义的静态和结构约束Java虚拟机中给出。在各个Java虚拟机指令的描述中,我们经常声明某些情况“必须”或“绝不”是这种情况:“value2必须是int类型。” [§4 (*The class File Format*)](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html) 中保证满足所有这些要求。如果一些指令中未明确定义其在运行时的约束(“必须”或“必须不”),则Java虚拟机的行为是不确定的。 2 | 3 | Java虚拟机使用类文件验证程序([§4.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.10))检查Java虚拟机代码是否在链接时满足静态和结构约束,使得Java虚拟机只会尝试执行有效的类文件中的代码。在链接时执行验证很有吸引力,因为检查只执行一次,大大减少了在运行时必须完成的工作量。其他实现策略也是可以的,只要它们符合Java语言规范。 -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/6.2_Reserved_Opcodes.md: -------------------------------------------------------------------------------- 1 | 在类文件中使用的 ([§4 (*The class File Format*)](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html)中,除了本章后面指定的指令的操作码外,还有三个保留操作码供Java虚拟机实现内部使用。如果将来扩展Java虚拟机的指令集,这些操作码需要被保证不会被使用。 2 | 3 | 两个保留的操作码,编号254(0xfe)和255(0xff),助记符分别为impdep1和impdep2。这些指令旨在分别为在软件和硬件中实现的特定于实现的功能提供“后门”或陷阱。第三个保留操作码,编号202(0xca),具有助记符断点,旨在供调试器用于实现断点。 4 | 5 | 虽然这些操作码已被保留,但它们只能在Java虚拟机实现中使用。它们不能出现在有效的类文件中。调试器或JIT代码生成器([§2.13](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.13))等可能与已经加载和执行的Java虚拟机代码直接交互的工具可能会遇到这些操作码。如果遇到任何这些保留的指令,这些工具应该尝试优雅地运行。 6 | 7 | 8 | -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/6.3_Virtual_Machine_Errors.md: -------------------------------------------------------------------------------- 1 | 当内部错误或资源限制阻止它实现本章中描述的语义时,Java虚拟机将抛出一个对象,该对象是VirtualMachineError子类的实例。该规范无法预测可能遇到内部错误或资源限制的位置,并且无法准确地确定何时可以报告它们。因此,在Java虚拟机的操作期间,可以随时抛出下面定义的任何VirtualMachineError子类: 2 | 3 | - *InternalError*: 由于实现虚拟机的软件故障,底层主机系统软件出现故障或硬件故障,Java虚拟机实现中发生内部错误。检测到此错误时会异步传送([§2.10](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.10)) ,并且可能在程序中的任何位置发生。 4 | - *OutOfMemoryError*:Java虚拟机实现已用完虚拟或物理内存,并且自动存储管理器无法回收足够的内存来满足对象创建请求。 5 | - *StackOverflowError*:Java虚拟机实现已经耗尽了线程的堆栈空间,通常是因为执行程序中的错误导致线程正在执行无限数量的递归调用。 6 | - *UnknownError*:发生了异常或错误,但Java虚拟机实现无法报告实际异常或错误。 -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/6.4_Format_of_Instruction_Descriptions.md: -------------------------------------------------------------------------------- 1 | Java虚拟机指令在本章中依次按字母序展示。 2 | 3 | > **助记词** 4 | 5 | **操作** 6 | 7 | ​ 指令的简短介绍 8 | 9 | **格式** 10 | 11 | ``` 12 | 助记词 13 | 操作一 14 | 操作二 15 | ``` 16 | 17 | **形式** 18 | 19 | ​ 助记词 = 操作符 20 | 21 | **操作数栈** 22 | 23 | ​ ..., *value1*, *value2* → 24 | 25 | ​ ..., *value3* 26 | 27 | **描述** 28 | 29 | ​ 详细描述操作数堆栈内容或常量池条目的约束,执行的操作,结果的类型等。 30 | 31 | **链接异常** 32 | 33 | ​ 如果执行此指令可能引发任何链接异常,则必须按照抛出的顺序将它们在此展示。 34 | 35 | **运行时异常** 36 | 37 | ​ 如果执行此指令可能引发任何运行时异常,则必须按照抛出的顺序将它们在此展示。 38 | 39 | ​ 除了为指令列出的链接和运行时异常(如果有)之外,该指令不得抛出除VirtualMachineError或其子类的实例之外的任何运行时异常。 40 | 41 | **记录** 42 | 43 | ​ 不是指令规范必须的一部分,仅作为说明在指令末尾留出。 44 | 45 | ​ 指令格式图中的每个单元代表一个8位字节。指令的助记符就是它的名字。其操作码是它的数字表示,并以十进制和十六进制形式给出。实际上只有数字形式出现在Java虚拟机的类文件中。 46 | 47 | ​ 请记住,在编译时生成并嵌入Java虚拟机指令中的“操作数”,以及在运行时计算并在操作数堆栈上提供的“操作数”。虽然它们是从几个不同的区域提供的,但所有这些操作数代表相同的事情:要执行的Java虚拟机指令要操作的值。通过隐式地从其操作数堆栈中获取其操作数,而不是在其编译代码中明确地将它们表示为附加操作数字节,寄存器编号等,使得Java虚拟机的代码保持紧凑。 48 | 49 | ​ 一些相关指令以共享描述,格式和操作数堆栈图的形式展示。因此,一系列指令包括多个操作码和操作码助记符;只有系列助记符出现在指令格式图中,并且单独的表单行列出了所有成员助记符和操作码。例如,lconst_ 系列指令的Forms行,为该系列中的两个指令(lconst_0和lconst_1)提供助记符和操作码信息: 50 | 51 | *lconst_0* = 9 (0x9) 52 | 53 | *lconst_1* = 10 (0xa) 54 | 55 | ​ 在Java虚拟机指令的描述中,指令的执行对当前帧 ([§2.6.2](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6.2)) 的操作数堆栈([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6))的影响以文本方式表示,堆栈从左到右增长,每个值分开表示: 56 | 57 | ..., *value1*, *value2* → 58 | 59 | ..., *result* 60 | 61 | ​ 例如一个操作,该操作首先使用操作数堆栈顶部使用value2,和其下方的value1。作为执行指令的结果,value1和value2从操作数堆栈中弹出,并由指令计算出的结果值替换。由省略号(...)表示的其他操作数堆栈的其余部分不受指令执行的影响。 62 | 63 | long和double类型的值由操作数堆栈上的单个条目表示。 64 | 65 | *在Java®虚拟机规范的第一版中,long和double类型的操作数堆栈上的值分别在堆栈图中由两个条目表示。* -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/6.5_Instructions/aaload.md: -------------------------------------------------------------------------------- 1 | > **aaload** 2 | 3 | **操作** 4 | 5 | 从数组中加载引用 6 | 7 | **格式** 8 | 9 | ``` 10 | aaload 11 | ``` 12 | 13 | **形式** 14 | 15 | *aaload* = 50 (0x32) 16 | 17 | **操作数栈** 18 | 19 | ..., *arrayref*, *index* → 20 | 21 | ..., *value* 22 | 23 | **描述** 24 | 25 | arrayref必须是类型引用,并且必须引用其组件类型为reference的数组。index必须是int类型,arrayref和index都从操作数堆栈中弹出。取出数组索引处元素的引用值将其推送到操作数栈。 26 | 27 | **运行时异常** 28 | 29 | **如果arrayref为null,则aaload会抛出NullPointerException。** 30 | 31 | **否则,如果index不在arrayref引用的数组范围内,则aaload指令会抛出ArrayIndexOutOfBoundsException。** 32 | 33 | -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/6.5_Instructions/aastore.md: -------------------------------------------------------------------------------- 1 | > ***aastore*** 2 | 3 | **操作** 4 | 5 | 存储进引用数组中 6 | 7 | **格式** 8 | 9 | ``` 10 | aastore 11 | ``` 12 | 13 | **形式** 14 | 15 | *aastore* = 83 (0x53) 16 | 17 | **操作数栈** 18 | 19 | ..., *arrayref*, *index*, *value* → 20 | 21 | ... 22 | 23 | **描述** 24 | 25 | arrayref必须为引用类型,切其指向的数组元素也必须是引用类型。index必须为int类型,value必须为引用类型。arrayref,index,value位于操作数栈中,在使用时会弹出。 26 | 27 | 如果value为null,其也将做为数据存储在对应位置。 28 | 29 | 如果value不为null,如果值的类型与arrayref引用的数组的元素类型兼容,则value也将存储在数组对应位置。 30 | 31 | 以下规则将用于确认value类型是否与数组元素类型兼容。定义S为value所引用对象的类型,T为数组元素的类型: 32 | 33 | - 如果S为class类型: 34 | - 如果T为class类型,则S必须与T类型相同,或S为T的子类。 35 | - 如果T为interface类型,则S必须实现了接口T。 36 | - 如果S为数组类型SC[] ,即数组元素类型为SC: 37 | - 如果T为class类型,这T必须是Object。 38 | - 如果T为interface类型,则T必须数组实现的其中一个接口(JLS §4.10.3) 39 | - 如果T是数组类型TC [],即TC类型的组件数组,则必须满足以下条件之一: 40 | - TC和SC是相同的原始类型。 41 | - TC和SC是引用类型,SC类型可通过这些运行时规则分配给TC。 42 | 43 | **运行时异常** 44 | 45 | **如果arrayref为null,aastore会抛出NullpointerException** 46 | 47 | **或者,如果index不在arrayref引用的数组范围内,则aastore指令会抛出ArrayIndexOutOfBoundsException。** 48 | 49 | **如果arrayref不为null且非null值的实际类型与数组的元素的实际类型不兼容,则aastore会抛出ArrayStoreException。** -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/6.5_Instructions/aconst_null.md: -------------------------------------------------------------------------------- 1 | > *aconst_null* 2 | 3 | **操作** 4 | 5 | ​ 压入null 6 | 7 | **格式** 8 | 9 | > *aconst_null* 10 | 11 | **形式** 12 | 13 | *aload* = 25 (0x19) 14 | 15 | **操作数栈** 16 | 17 | ... → 18 | 19 | ..., *objectref* 20 | 21 | **描述** 22 | 23 | Index是一个无符号字节,必须是当前帧的局部变量数组的索引([§2.6](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6))。位于索引处的局部变量必须包含一个引用。索引处的局部变量中的objectref被压入操作数堆栈。 24 | 25 | **注意** 26 | 27 | 与astore指令 ([§*astore*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.astore)) 不同,aload指令不能用于将类型为returnAddress的值从局部变量加载到操作数栈中。 28 | 29 | 可以将aload操作码与wide指令([§*wide*](https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-6.html#jvms-6.5.wide)) 结合使用,以使用两字节无符号索引访问局部变量。 -------------------------------------------------------------------------------- /6-The_Java_Virtual_Machine_Instruction_Set/The_Java_Virtual_Machine_Instruction_Set.md: -------------------------------------------------------------------------------- 1 | Java虚拟机指令由指定要执行的操作的操作码和操作数组成。本章详细介绍了每个Java虚拟机指令的格式及其执行的操作。 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | .-') _ ('-. .-. ('-. (`-. _ .-') .-') _ (`-. ('-. 3 | ( OO) ) ( OO ) /_( OO) _(OO )( '.( OO )_ ( OO ). ( (OO )_( OO) 4 | / '._,--. ,--(,------. ,--,--(_/ ,. ,--. ,--.) (_)---\__.` (,------. .-----. 5 | |'--...__| | | || .---' .-')| ,\ \ /(__| `.' | / _ (__...--''| .---' ' .--./ 6 | '--. .--| .| || | ( OO |(_|\ \ / /| | \ :` `.| / | || | | |('-. 7 | | | | (| '--. | `-'| | \ ' /,| |'.'| | '..`''.| |_.' (| '--. /_) |OO ) 8 | | | | .-. || .--' ,--. | | \ /__| | | | .-._) | .___.'| .--' || |`-'| 9 | | | | | | || `---. | '-' / \ / | | | | \ | | | `---(_' '--'\ 10 | `--' `--' `--'`------' `-----' `-' `--' `--' `-----'`--' `------' `-----' 11 | ``` 12 | 13 | # The Java® Virtual Machine Specification 14 | 15 | **Java SE 12 Edition** 16 | 17 | Java虚拟机规范(Java SE 12) 中文翻译 18 | 19 | https://docs.oracle.com/javase/specs/jvms/se12/html/index.html 20 | 21 | huifrank01#gmail.com 22 | 23 | 文件名,标题未翻译。已更新的内容都是中文的。 24 | 25 | 持续更新中 26 | 27 | ``` 28 | 29 | 30 | The-Java-Virtual-Machine-Specification/ 31 | ├── 1-Introduction 32 | │ ├── 1.1_A_Bit_of_History.md 33 | │ ├── 1.2_The_Java_Virtual_Machine.md 34 | │ ├── 1.3_Organization_of_the_Specification.md 35 | │ ├── 1.4_Notation.md 36 | │ └── 1.5_Feedback.md 37 | ├── 2-The_Structure_of_The_Java_Virtual_Machine 38 | │ ├── 2.1_The_class_File_Format.md 39 | │ ├── 2.2_Data_Types.md 40 | │ ├── 2.3_Primitive_Types_and_Values 41 | │ │ ├── 2.3.1_Integral_Types_and_Values.md 42 | │ │ ├── 2.3.2_Floating-Point_Types_Value_Sets_and_Values.md 43 | │ │ ├── 2.3.3_The_returenAddress_Type_and_Values.md 44 | │ │ ├── 2.3.4_The_boolean_Type.md 45 | │ │ └── Primitive_Types_and_Values.md 46 | │ ├── 2.4_Reference_Types_and_Values.md 47 | │ ├── 2.5_Run-Time_Data_Areas 48 | │ │ ├── 2.5.1_The_pc_Register.md 49 | │ │ ├── 2.5.2_Java_Virtual_Machine_Stacks.md 50 | │ │ ├── 2.5.3_Heap.md 51 | │ │ ├── 2.5.4_Method_Area.md 52 | │ │ ├── 2.5.5_Run-time_Constant_Pool.md 53 | │ │ ├── 2.5.6_Native_Method_Stacks.md 54 | │ │ └── Run-Time_Data_Areas.md 55 | │ ├── 2.6_Frames 56 | │ │ ├── 2.6.1_Local_Variables.md 57 | │ │ └── Frames.md 58 | │ └── The_Structure_of_the_Java_Virtual_Machine.md 59 | ├── 4-The_class_File_Format 60 | │ ├── 4.1_The_ClassFile_Structure.md 61 | │ └── The_class_File_Format.md 62 | ├── 5-Loading_Linking_and_Initializing 63 | │ ├── 5.1_The_Run-Time_Constant_Pool.md 64 | │ ├── 5.2_Java_Virtual_Machine_Startup.md 65 | │ ├── 5.3_Creation_and_Loading.md 66 | │ └── Loading_Linking_and_Initializing.md 67 | ├── 6-The_Java_Virtual_Machine_Instruction_Set 68 | │ ├── 6.1_Assumptions_The_Meaning_of_Must.md 69 | │ ├── 6.2_Reserved_Opcodes.md 70 | │ ├── 6.3_Virtual_Machine_Errors.md 71 | │ ├── 6.4_Format_of_Instruction_Descriptions.md 72 | │ ├── 6.5_Instructions 73 | │ │ └── aaload.md 74 | │ └── The_Java_Virtual_Machine_Instruction_Set.md 75 | └── README.md 76 | ``` 77 | 78 | --------------------------------------------------------------------------------