Java类链接解析步骤或初始化是否导致其他解析类的加载? [英] Does Java Class Linkage Resolution step OR Initialisation lead to loading of other resolved classes?

查看:93
本文介绍了Java类链接解析步骤或初始化是否导致其他解析类的加载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究JVM规范文档和JLS,涉及Java中的类加载机制。



这是我的理解。


  1. 起初是什么时候主类被要求加载,它
    查看该类的二进制表示形式是否已经被
    加载,如果不是,则类加载器从磁盘中的
    加载类文件。


  2. 链接步骤:验证,准备和解决方案


  3. 初始化。




我发现令人困惑的是,在解析和初始化步骤中,如果引用了一个尚未从源代码加载的类,会发生什么?



还是将加载,链接和初始化推迟到使用该方法的实际方法或代码使用时,解析或初始化步骤才会暂停,以使类加载由其父类加载器完成吗?引用是在运行时执行的?

解决方案

JVMS§5.4。链接状态:


链接类或接口涉及验证和准备该类或接口,其直接超类,其直接超接口。 ,以及其元素类型(如果是数组类型)(如果需要)。解决类或接口中的符号引用是链接的可选部分。


因此,当不谈论类的直接超类型时, ,分辨率为可选,并且可能会延迟。



同一部分还包含



<例如,一个Java虚拟机实现可以选择在使用某个类或接口时分别解析每个符号引用(懒惰或最新分辨率),或者全部解决它们。在验证类别时立即解决(紧急或静态解决方案)。这意味着在某些实现中,解析过程可能会在初始化类或接口之后继续。


因此,该过程不会始终严格按照问题中显示的图形进行操作。相反,解决方案可以看作是一个持续的过程。



在实践中,对于HotSpot JVM,某些类(如超类)必须立即得到解决。验证方法的代码时会解析其他类,该类恰好在为此JVM首次执行方法之前发生。



这不会影响该方法的引用的所有类代码,但取决于实际的类型使用,例如HotSpot的验证程序将解析类型,以根据实际的类型层次结构检查分配的有效性,但如果将类型分配给自身或 java.lang.Object ,请跳过此步骤,即分配始终有效的位置。因此,某些类型只能在首次实际使用时才能解决,例如通过 new 或由类型声明的 static 方法实例化它们时。但这取决于代码的微妙方面。另请参见何时加载Java类?如果缺少未使用的类,JVM会抛出吗?



可能只有在反射数据中引用的类型,例如注释或调试属性,它们会得到



但是由于这意味着类型的解析会推迟到实际需要的时候,因此它也可以在另一个解析中解决。表示此时,操作将停止并等待先决条件类的此过程完成。因此,例如加载一个类始终意味着解析其直接超类,如果尚未加载则对其进行加载,这反过来又意味着解析该超类的超类,依此类推。因此它不会在完整的超类层次结构解决之前返回。


I was going through the JVM specification document and JLS , on the classloading mechanism in java .

Here is what I understand .

  1. At first the when the main class is being asked to be loaded , it looks if the binary representation of the class has been already loaded or not , if not the class loader loads the class file from the disk .

  2. Linkage Steps: Verification ,Preparation and Resolution

  3. Initialisation.

What I find confounding is , while in the Resolution and Initialisation steps if a class is referenced which has yet not been loaded from the source , what happens ? does the Resolution or Initialisation step pause for the Classloading to happen by it's parent classloader?

Or is the loading , Linking and Initialization deferred till the time actual method or code using that reference is executed at runtime ?

解决方案

JVMS §5.4. Linking states:

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.

So when not talking about the direct supertypes of a class, the resolution is optional and may be deferred.

The same section also contains

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.

So the process does not always strictly follow the graphic you’ve shown in the question. Instead, the resolution can be seen as an ongoing process.

In practice, in case of the HotSpot JVM, some classes have to get resolved immediately, like the superclasses. Other classes are resolved when verifying code of a method, which happens right before the first execution of a method for this JVM.

This does not affect all classes referenced by a method’s code but depend on the actual type use, e.g. HotSpot’s verifier will resolve types for checking the validity of assignments against the actual type hierarchy, but skip this step, if a type is assigned to itself or to java.lang.Object, i.e. where the assignment is always valid. So some types may get resolved only at their first actual use, e.g. when they are instantiated via new or a static method declared by the type is invoked. But this depends on subtle aspects of the code. See also When is a Java Class loaded? or Does the JVM throw if an unused class is absent?

There might be types referenced only in reflective data like annotations or debug attributes which get never resolved during a run, but may be in another.

But since this implies that the resolution of a type is deferred to the point when it is actually needed, it also implies that right at this point, the operation will stop and wait for the completion of this process for the prerequisite classes. So, e.g. loading a class always implies resolving its direct superclass, loading it if not already loaded, which in turn implies resolving of the superclass of the superclass and so on. So it won’t return before the complete super class hierarchy has been resolved.

这篇关于Java类链接解析步骤或初始化是否导致其他解析类的加载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆