Java类加载的解析阶段实际上从哪里开始?

 乖扬123_829 发布于 2023-02-13 11:48

我刚读完Java虚拟机规范,关于类加载的部分让我感到困惑.据我所知,在阅读规范之后,我认为类的整体实例化按以下顺序组成:

创建/加载:类加载器定位表示类的字节流,可以是文件或网络流,也可以是实现要获取的类加载器的任何类型.如果找不到类,ClassNotFoundException则抛出a.此时,ClassFormatError如果字节数组不表示Java类(例如,缺少幻数)或者UnsupportedClassVersionError正在运行的JVM实例不支持类版本,则已经发生了一些基本验证.

链接:该类被挂钩到JVM中.如果出现问题,LinkageError则抛出一个子类.链接由三个子步骤组成:

验证:确保字节流表示Java类,例如字节代码没有形式错误,例如溢出操作数堆栈的方法字节代码.如果一个类验证失败,VerifyError则抛出一个.

准备:JVM为所有静态字段分配内存,并可能创建实例模板以加速实例创建.创建虚拟方法表.在此阶段不会抛出类加载特定错误.(OutOfMemoryError虽然可能会抛出.)

解决方案:现在以运行时常量池的形式加载到方法区域中的所有符号引用都将解析为此JVM加载的实际类型.如果可以解析符号引用但导致定义冲突,IncompatibleClassChangeError则抛出a.如果找不到引用的类,NoClassDefFoundError则抛出a ClassNotFoundException,它基本上包装了类加载器尝试加载此引用类所引发的类.如果引用的类引用自身,ClassCircularityError则抛出a.解决方案可以以两种方式之一发生,这取决于JVM的实现者

    渴望:现在解决对其他字段,方法或类的所有符号引用.

    懒惰:将符号引用的解析推迟到第一次使用方法时.这可能会带来一个引用不存在的类的类永远不会抛出错误,如果这个引用永远不需要解决.

初始化:运行在类static中定义为Java代码的类的初始化程序.如果这样的初始化程序引起异常,则会重新包含此异常ExceptionInInitializerError.

令我困惑的是上述类加载机制的解析阶段.为什么分辨率被定义为链接中的明确步骤,具体在准备之后发生?已经在类加载阶段的描述中,提到了

如果C具有任何直接超接口,则使用§5.4.3.1的算法解析从C到其直接超接口的符号引用.

验证发生后,符号引用是否也未得到解决,因为描述了验证:

验证(第4.10节)确保类或接口的二进制表示在结构上是正确的(第4.9节).验证可能会导致加载其他类和接口(第5.3节),但不需要对它们进行验证或准备.

我总是记住这张照片

Java类加载概述

资料来源:http://www.programcreek.com

我几乎在任何解释课程加载的地方都看到过.如果分辨率不情愿被看作是所有阶段的一部分,全面负责创建/加载,验证,连接初始化(因为分辨率可以懒洋洋地完成).

目前,我认为从该图像中取出解决阶段并将其声明为可以随时使用的一般过程是有意义的,因为在任何阶段可能需要关于其他类的信息,以便加载这样的class是必需的,也必然需要解析这个类的符号引用.从显示的图片看,分辨率只发生在一系列独立事件的特定点上.

我怀疑这描绘的分辨率是从那里时专用的工序,也许只是传统分辨率从未懒洋洋进行,但有它的地方,所有剩余的符号引用得到解决.

我想知道的是:今天的JVM中的分辨率应该按照我描述的方式理解吗?或者我错了,解决方案仍然可以被理解为固定时间线中的专用步骤,就像图像显示的那样?

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有