Java虚拟机动态的加载、链接、初始化类或接口。加载是通过特定的名字找到类或接口类型的二进制表示,根据找到的二进制表示创建类或接口的过程。链接是获得创建的类,将它们结合进Java虚拟机的运行时状态以使他们能够被执行的过程。初始化一个类或接口包括执行类或接口的初始化方法<clinit>.
5.1 运行时常量池
Java虚拟机为每一个类型维续一个常量池,一种运行时的数据结构,提供类似于传统语言中符号表的服务。
类或接口的二进制表示中的常量池表被用来在类或接口创建时构建运行时常量池。运行时常量池中的所有引用都是原始的符号,常量池中的引用按照如下规则从类或接口的二进制表示中推断出来:
- 一个类或接口的符号引用从类或接口的二进制表示的CONSTANT_Class_info中推断出来。这个引用按照Class.getName方法的返回值的形式给出类或接口的名字,即:
- 对于非数组的类或接口,这个名字就是对应类或接口的二进制名字。
- 对于n维的数组,这个名字以n个ASCII字符"["开头,紧跟着数组的元素类型:
> 如果元素是基本类型,就是相应的类型的描述符(B C D F I J S Z)对应着 byte char double float int long short boolean
> 否则,对应的元素就是引用类型,这时会用ASCII字符"L"加上对应元素的二进制名字,并在后面加上ASCII字符";"来表示。
以上信息可以通过javap -v {className} 命令查看
本章节中只要提及类或接口的名字,都是指Class.getName方法的返回值的形式。
- 对一个类或接口的字段的符号引用由类或接口的二进制表示中的CONSTANT_Fieldref_info结构中推导出来。这样一个符号引用会给出对应字段的名字和描述符,还会给出这个字段所在类或接口对应的符号引用。
- 对一个类的方法的符号引用由类或接口的二进制表示中的CONSTANT_Methodref_info结构中推导出来。这样一个符号引用会给出对应方法的名字和描述符,还会给出这个方法所在类对应的符号引用。
- 对一个接口的方法的符号引用由类或接口的二进制表示中的CONSTANT_InterfaceMethodref_info结构中推导出来。这样一个符号引用会给出对应方法的名字和描述符,还会给出这个方法所在类对应的符号引用。
- 对一个method handle的符号引用,由类或接口的CONSTANT_MethodHandle_info结构中推导出来。根据method handle类型的不同,这样一个引用可以给出一个类或接口的字段符号引用,或者是类的一个方法的引用,或者是一个接口的方法的引用。
- 对一个method type的符号引用从CONSTANT_MethodType_info结构中推导出来,这样的一个引用给出一个方法的描述符。
- 对一个call site specifier的符号引用从CONSTANT_InvokeDynamic_info结构中推导出来,这样的引用会给出:
- 一个method handle的符号引用,这个引用会在invokedynamic指令中作为一个启动方法。
- 一连串的符号引用(对一个类、方法类型、method handle),字符串字面值,运行常量值,它们会做为启动方法的静态参数。
- 一个方法名字和一个方法描述
另外,非符号引用的运行时常量值从constant_pool中查找:
一个字符串字面值是一个String类型的引用,从CONSTANT_String_info结构中推导出来,CONSTANT_String_info结构是一系列的Unicode码组成了字符串字面值。
Java编程语言要求相同的字符串字面值一定要指向相同的String类实例。另外,如果一个任意字符串的String.intern方法被调用,如果这个字符串之前已经出现过,那么返回结果将是同一个类实例。因此下面的表达式的结果是true
("a" + "b" + "c").intern() == "abc"
为了推导出字符串字面值,Java虚拟机会用下面的规则检测CONSTANT_String_info结构的字符序列:
- 如果一个String类实力已经调用过它的intern方法,并且这个这个字符串拥有和CONSTANT_String_info结构一样的Unicode 码序列,那么这个字符串字面值就是同一个字符串实例的一个引用。
- 否则一个新的包含了CONSTANT_String_info结构中Unicode码序列的字符串实例就会被创建,一个指向新创建的字符串的引用作为字符串字面值的结果,最终,这个新字符串的intern方法被调用。
运行时常量数值从CONSTANT_Integer_info,CONSTANT_Float_info, CONSTANT_Long_info, 、CONSTANT_Double_info结构中推导出来
类或接口的二进制表示常量池表中其他的结构有CONSTANT_NameAndType_info和CONSTANT_Utf8_info,它们仅被直接用来推导出类、接口、字段、方法、方法类型、method handles的符号引用,或者是用来推导出字符串字面值和call site说明符。
5.2 Java虚拟机启动
Java虚拟机通过创建一个初始化类类启动,利用引导类加载器。Java虚拟机紧接着链接、初始化这个类,调用它的public void main(String[]) 类方法。对这个方法的调用带动所有的后续操作。执行组成main方法的Java虚拟机指令可能会引起链接其他的类或接口,也可能会调用其他的方法。
在Java虚拟机的实现中,初始化类可以通过命令行参数提供。或者实现者也可以提供一个设定类加载器的初始化类,用这个类加载器来加载一个应用。
分享到:
相关推荐
运行时常量池是方法区内的一部分,用于存储类或接口的常量信息,包括但不限于字符串常量、类和接口的符号引用等。这些信息是在类加载阶段创建的,并且在整个应用的生命周期中保持不变。 ##### 1.5 本地方法栈 ...
在第16章中,我们将深入探讨Java类的加载、连接和初始化过程,以及反射的核心概念。 **16.1 类的加载、连接和初始化** 类的加载是Java程序运行的基础,它涉及到三个关键步骤: 1. **加载**:当程序首次尝试使用...
整个过程可以分为五个主要步骤:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)和初始化(Initialization)。在Java虚拟机规范中,这些步骤确保了类的安全性和正确性。 1. 加载...
类加载过程主要包括五个步骤:加载、验证、准备、解析和初始化。 1. **加载(Loading)**:在这个阶段,虚拟机需要完成以下三件事情: - 通过一个类的全限定名来获取定义此类的二进制字节流。 - 将这个字节流所...
类的生命周期包括加载、验证、准备、解析和初始化五个阶段。加载是读取类文件并创建类的Class对象,验证确保字节码的正确性,准备为静态变量分配内存并设置默认初始值,解析将符号引用转换为直接引用,初始化执行类...
它主要涉及到类成员(包括静态和非静态)的加载和初始化过程。理解这些基础知识有助于更好地掌握Java语言特性。 **关键概念解析:** 1. **静态成员的初始化:** - **静态变量**:类加载时首先初始化。 - **静态...
java虚拟机规范,高清PDF版本,含有目录结构:第一章:引言; 第二章:java虚拟结构(运行时区域内存:寄存器,java虚拟机栈,java堆,方法去,运行时常量池,本地方法栈);... 第五章:加载、链接与初始化
类加载的过程涵盖了加载、验证、准备、解析和初始化这五个阶段,每个阶段都有其特定的任务,共同确保了类在JVM中的正确加载和安全运行。理解这些概念对于优化Java应用程序性能、理解和解决内存问题至关重要。
- **常量池**:包含常量和符号引用。 - **非RAM存储**:硬盘等永久存储,如持久化数据。 - **堆内存**:用于分配对象和数组,由垃圾回收器管理。 - **栈内存**:存储基本类型和引用,速度快但大小有限。 **四、Java...
在这五个阶段中,加载、验证、准备和初始化这四个阶段发生的顺序是确定的,而解析阶段如此不一定,它在某些情况下可以在初始化阶段之后开始,这是为了支持 Java 语言的运行时绑定(也成为动态绑定或晚期绑定)。...
《Java虚拟机规范(Java SE 7版)》是Java领域最...第5章定义了Java虚拟机启动以及类和接口的加载、链接和初始化过程。第6章阐释并列举了Java虚拟机指令集。第7章提供了一张以操作码值为索引的Java虚拟机操作码助记符表。
这一章详细阐述了Java源代码如何被编译成字节码,并讲解了类文件的结构,包括魔数、版本号、常量池、访问标志、类索引、父类索引、接口索引集合、字段表集合、方法表集合和属性表集合等元素。这些内容对于理解类的...
5. **初始化**:这是类加载的最后一步,在之前的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码...
5. **初始化**:执行程序员编写的类初始化代码,包括静态块等,以按需初始化类变量和其他资源。 6. **使用**:当类被主动引用时,如通过`new`关键字创建对象,或者调用类的静态方法,类会进入使用阶段。被动引用,...
- **常量池**:存储编译时确定的常量和符号引用。 - **非RAM存储**:如硬盘,用于持久化存储。 - **堆内存**:所有对象实例和数组都在这里分配,由垃圾收集器管理。 - **栈内存**:存储基本类型变量和对象引用,速度...
第28讲 Java内存区域-直接内存和运行时常量池 00:15:53 第29讲 对象在内存中的布局-对象的创建 00:21:19 第30讲 探究对象的结构 00:13:47 第31讲 深入理解对象的访问定位 00:08:01 第32讲 垃圾回收-...