Java Class 链接解析步骤或初始化是否导致加载其他已解析的 类?
Does Java Class Linkage Resolution step OR Initialisation lead to loading of other resolved classes?
我在 java 的 class 加载机制上浏览了 JVM 规范文档和 JLS 。
这是我的理解。
起初,当要求加载主要 class 时,它
查看 class 的二进制表示是否已经
加载与否,如果未加载,class 加载程序从中加载 class 文件
磁盘。
链接步骤:验证、准备和解决
初始化。
我发现令人困惑的是,如果在解析和初始化步骤中引用了尚未从源加载的 class,会发生什么情况?解析或初始化步骤是否暂停以使其父类加载发生 classloader?
或者加载、链接和初始化是否推迟到使用该引用的实际方法或代码在运行时执行时?
Linking a class or interface involves verifying and preparing that class or interface, its direct superclass, its direct superinterfaces, and its element type (if it is an array type), if necessary. Resolution of symbolic references in the class or interface is an optional part of linking.
因此,当不讨论 class 的直接超类型时,决议是 可选的 并且可以推迟。
同一节还包含
For example, a Java Virtual Machine implementation may choose to resolve each symbolic reference in a class or interface individually when it is used ("lazy" or "late" resolution), or to resolve them all at once when the class is being verified ("eager" or "static" resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized.
所以这个过程并不总是严格按照你在问题中显示的图形进行。相反,该决议可以被视为一个持续的过程。
实际上,在 HotSpot JVM 的情况下,一些 classes 必须立即得到解决,比如 superclasses。其他 classes 在验证方法代码时解决,这发生在第一次执行此 JVM 的方法之前。
这不会影响方法代码引用的所有 classes,但取决于实际类型的使用,例如HotSpot 的验证器将解析类型以根据实际类型层次结构检查分配的有效性,但如果类型分配给自身或分配给 java.lang.Object
,即跳过此步骤,即分配始终有效。因此,某些类型可能仅在首次实际使用时才得到解决,例如当它们通过 new
实例化或调用类型声明的 static
方法时。但这取决于代码的微妙方面。另见 or
可能有些类型仅在反射数据中引用,例如在 运行 期间从未解决的注释或调试属性,但可能在另一个
中
但是因为这意味着类型的解析被推迟到实际需要的时候,也意味着就在这个时候,操作将停止并等待这个过程的完成作为前提classes。所以,例如加载一个 class 总是意味着解析它的直接 superclass,如果还没有加载就加载它,这反过来意味着解析 superclass 的 superclass 等等.所以它不会 return 在完整的超级 class 层次结构被解析之前。
JVMS 在第 5.3 节中也有说明
If the Java Virtual Machine ever attempts to load a class C during verification
(§5.4.1) or resolution (§5.4.3) (but not initialization (§5.5)), and the class loader
that is used to initiate loading of C throws an instance of ClassNotFoundException ,
then the Java Virtual Machine must throw an instance of NoClassDefFoundError
whose cause is the instance of ClassNotFoundException .
(A subtlety here is that recursive class loading to load superclasses is performed
as part of resolution (§5.3.5, step 3). Therefore, a ClassNotFoundException that
results from a class loader failing to load a superclass must be wrapped in a
NoClassDefFoundError .)
所以在类加载的解析阶段确实存在递归。
我在 java 的 class 加载机制上浏览了 JVM 规范文档和 JLS 。
这是我的理解。
起初,当要求加载主要 class 时,它 查看 class 的二进制表示是否已经 加载与否,如果未加载,class 加载程序从中加载 class 文件 磁盘。
链接步骤:验证、准备和解决
初始化。
我发现令人困惑的是,如果在解析和初始化步骤中引用了尚未从源加载的 class,会发生什么情况?解析或初始化步骤是否暂停以使其父类加载发生 classloader?
或者加载、链接和初始化是否推迟到使用该引用的实际方法或代码在运行时执行时?
Linking a class or interface involves verifying and preparing that class or interface, its direct superclass, its direct superinterfaces, and its element type (if it is an array type), if necessary. Resolution of symbolic references in the class or interface is an optional part of linking.
因此,当不讨论 class 的直接超类型时,决议是 可选的 并且可以推迟。
同一节还包含
For example, a Java Virtual Machine implementation may choose to resolve each symbolic reference in a class or interface individually when it is used ("lazy" or "late" resolution), or to resolve them all at once when the class is being verified ("eager" or "static" resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized.
所以这个过程并不总是严格按照你在问题中显示的图形进行。相反,该决议可以被视为一个持续的过程。
实际上,在 HotSpot JVM 的情况下,一些 classes 必须立即得到解决,比如 superclasses。其他 classes 在验证方法代码时解决,这发生在第一次执行此 JVM 的方法之前。
这不会影响方法代码引用的所有 classes,但取决于实际类型的使用,例如HotSpot 的验证器将解析类型以根据实际类型层次结构检查分配的有效性,但如果类型分配给自身或分配给 java.lang.Object
,即跳过此步骤,即分配始终有效。因此,某些类型可能仅在首次实际使用时才得到解决,例如当它们通过 new
实例化或调用类型声明的 static
方法时。但这取决于代码的微妙方面。另见
可能有些类型仅在反射数据中引用,例如在 运行 期间从未解决的注释或调试属性,但可能在另一个
中但是因为这意味着类型的解析被推迟到实际需要的时候,也意味着就在这个时候,操作将停止并等待这个过程的完成作为前提classes。所以,例如加载一个 class 总是意味着解析它的直接 superclass,如果还没有加载就加载它,这反过来意味着解析 superclass 的 superclass 等等.所以它不会 return 在完整的超级 class 层次结构被解析之前。
JVMS 在第 5.3 节中也有说明
If the Java Virtual Machine ever attempts to load a class C during verification (§5.4.1) or resolution (§5.4.3) (but not initialization (§5.5)), and the class loader that is used to initiate loading of C throws an instance of ClassNotFoundException , then the Java Virtual Machine must throw an instance of NoClassDefFoundError whose cause is the instance of ClassNotFoundException . (A subtlety here is that recursive class loading to load superclasses is performed as part of resolution (§5.3.5, step 3). Therefore, a ClassNotFoundException that results from a class loader failing to load a superclass must be wrapped in a NoClassDefFoundError .)
所以在类加载的解析阶段确实存在递归。