Java 虚拟机 (JVM) 在幕后做了很多工作来执行提交给它执行的二进制类文件。并不是那么简单,因为它看起来就像使用 java 命令调用 JVM,并将类文件作为命令行参数传递给它。类文件经历了许多阶段,但在这里我们基本上看见了最初的三个执行阶段,称为加载、链接和初始化过程。即便如此,它本身就是一个巨大而复杂的话题。因此,这里只简要描述了关键方面,以了解它的全部内容。

概述

加载、链接和初始化是 JVM 在将字节码(称为类文件)加载到 JVM 中执行时立即开始的初始过程。其他过程——例如实例化、垃圾收集和终结——发生在类生命周期的中间阶段。最后,卸载过程发生在生命周期的末尾。JVM 提供了不同进程运行的环境。使用什么语言编译器将源代码转换为类文件绝对无关紧要,只要它符合 JVM 理解的标准。

除了 Java,还有很多知名的 JVM 语言,如 Clojure、Groovy、Scala、Jruby、Jython 等。程序可以用这些语言中的任何一种编写,并由特定语言编译器编译。编译后的目标代码以在 JVM 上运行的方式创建。

尽管 JVM 为类文件的执行强加了某些规则,但在底层,它可以修改它在底层平台上的交互方式并优化性能。这个想法使它成为一个开放的架构,欢迎特定于供应商的调整,以使其在某些情况下变得更好。

因此,除了 JVM 的 Oracle 和 OpenJDK 实现之外,市场上还有其他可用的活跃实现,例如 CACAO、jikes RVM、Maxine、JamVM 等。在java培训中,培训课程不仅注重理论,更注重项目的实战能力,能够让你快速适应企业开发的进度,成为企业所需要的java人才。

加载、链接和初始化过程是在将类文件导入 JVM 的开始阶段启动的。尽管其中涉及很多错综复杂的内容,但如果我们深入探讨这个主题而只留下其他 JVM 进程,那么这个想法就会变得过于密集而无法清晰理解。这是因为一个想法与另一个想法是相互关联的。例如,如果在加载阶段出现错误,报告会等到链接器开始发挥作用。因此,加载、链接和初始化的想法可能看起来是离散的,但它们在许多情况下重叠。

类文件之旅

Java 类文件的生命周期之旅:Java 编译器创建一个类文件,作为作为源代码提供给它的文件的结果。类文件虽然是二进制数据,但远不能在没有 Java 虚拟机 (JVM) 的机器上执行。这意味着类文件完全依赖JVM环境来执行。JVM 提供运行时环境并理解类文件中表示的二进制指令。与底层平台交互执行类文件指令的是JVM。中间人 JVM 不仅为类文件提供了游乐场,而且还充当了交换服务和资源的中介。因此,如果我们分解JVM成功执行一个类文件所承担的进程,它们是很多的。但是,首先,JVM 在将类文件导入其域的初始阶段遵循三个过程。这三个过程称为加载、链接和初始化。

加载过程

根据 Java 8 虚拟机规范,它是查找具有特定名称的类或接口类型的二进制表示并从该二进制表示创建类或接口的过程。

JVM 提供了两种类型的类加载器。一种称为引导类加载器,另一种是用户定义的类加载器。bootstrap 类加载器在 JVM 中被严格定义,并根据规范加载类文件。用户定义的类加载器对供应商特定的实现是开放的,并且可以通过 java.lang.Class 实例自定义加载类。请注意(在 Java API 文档中),此类没有公共构造函数。因此,类对象由JVM自动创建,并且可以通过该类的成员函数获取有关类内部数据结构的所有信息。一旦加载了一个类,JVM就会根据内部数据结构对其进行解析。通常,类加载器在加载时或提前或与一组类相关时缓存类型的二进制表示。如果遇到任何问题,即使在加载的初始阶段,例如由于类格式错误,它也不会立即报告问题;相反,它会等到程序主动引用该类并报告链接器错误。如果在整个程序过程中没有进行此类引用,则错误可能会持续存在但不会报告。

因此,简而言之,加载过程基本上完成了这三个功能:

从类文件创建二进制数据流

根据内部数据结构解析二进制数据

创建 java.lang.Class 的实例

链接过程

根据 Java 8 虚拟机规范,它是获取类或接口并将其组合到 JVM 的运行时状态以便可以执行的过程。

链接从类的验证过程开始,确保它符合语言的语义并且不会破坏 JVM 的完整性。但是,JVM 规范说明了验证过程,但为特定于供应商的 JVM 实现者提供了灵活性,以决定何时应该进行链接活动或如何验证类型。

JVM 指定了在特定情况下要抛出的异常列表。在这方面,值得一提的是,从二进制数据被解析到内部数据结构的一开始,就有一点点的检查和验证,这个过程中的检查确保了操作不会崩溃。此外,还进行检查以确保二进制数据的结构与其预期的格式一致。加载器还检查一个类是否是 java.lang.Object 的子类,唯一的例外是 Object 类本身。这通常需要递归加载超类层次结构。以这种方式,在多个阶段进行大量验证,但通常认为正式验证从链接开始。

验证完成后,JVM 为类变量分配内存,并根据变量的类型将它们初始化为默认值。然而,实际初始化(使用用户定义的初始化值)直到下一个初始化阶段才会发生。这个过程称为准备。

最后,在可选的解析阶段,JVM 定位常量池(符号表)中引用的类、接口、字段和方法,并从它们的符号引用中确定具体值。Java 符号引用解析同样对特定于供应商的实现开放。它可能决定在使用时解析类或接口中的符号引用,或者在验证过程中解析它们。简而言之,验证检查类的二进制表示在结构上是否正确。并且,它可能确保它可能必须加载其他类(可能)而无需验证这些类(如果这些类是 Java API 库的一部分)。

因此,简而言之,链接过程涉及三个功能:

确认

准备

分辨率(可选)

初始化过程

根据 Java 8 虚拟机规范,类或接口的初始化包括执行其类或接口的初始化方法。

在通过验证、准备和可选解析过程链接类或接口之后,初始化阶段使类准备好进行第一次活动使用。该过程从使用程序预期开始的值初始化类变量开始。程序员有责任根据自己的宏伟计划决定类变量的适当值。因此,初始化意味着类变量通过程序员描述的一些初始化例程进行初始化,并在类的直接超类尚未初始化的情况下对其进行初始化。然而,接口的初始化不需要初始化它的超接口。这是一个接口的例外。

因此,概括起来,初始化过程涉及以下两个功能:

用程序员指定的例程初始化类变量。

如果尚未初始化,则初始化其超类。

结论

这是对 JVM 中加载、链接和初始化过程的简要概述,每个阶段都涉及许多更精细的复杂性,并且为了保持简单和简洁而被忽略了。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部