【问题标题】:Initialization-on-demand holder idiom - When are classes loaded?Initialization-on-demand holder idiom - 什么时候加载类?
【发布时间】:2018-10-24 15:11:55
【问题描述】:

我一直在看:https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom 以了解更多关于单身人士的信息。

我的问题是静态内部类究竟什么时候被加载,什么时候被初始化?我的理解是可以加载类,但在绝对需要初始化之前保持未初始化。

如果类没有加载,JVM内部如何指定私有静态内部类?

【问题讨论】:

    标签: java jvm internals


    【解决方案1】:

    类初始化的确切时间,在Java® Language Specification, §12.4.1中指定

    §12.4.1。初始化发生时

    类或接口类型 T 将在以下任何一项第一次出现之前立即初始化:

    • T 是一个类,并创建了一个 T 的实例。
    • 调用T 声明的static 方法。
    • 分配了T 声明的static 字段。
    • 使用了由T 声明的static 字段,并且该字段不是常量变量(§4.12.4)。
    • T 是一个顶级类 (§7.6),并且在 T (§8.1.3) 中的词法嵌套的 assert 语句 (§14.10) 被执行。

    当一个类被初始化时,它的超类被初始化(如果它们之前没有被初始化),以及声明任何默认方法(§9.4.3)的任何超接口(@98​​7654326@)(如果它们之前没有被初始化)初始化)。接口的初始化本身不会导致其任何超接口的初始化。

    Java 9 中的最后一个项目符号已被删除

    加载的时间不是固定的,可能取决于实现细节,例如验证器是如何实现的。但显然,它必须发生在初始化之前。

    从 JVM 的角度来看,这是一个嵌套类这一事实并没有什么特别的意义。在外部类 constant pool 中有一个对内部类的符号引用,就像任何其他引用的类一样。需要时将是resolved

    【讨论】:

    • 非常感谢!几个后续问题。您提到加载取决于实现。究竟是什么实现?类加载是否在类加载器中确定?我一直在读到一些类加载器实现会急切地加载类,而有些则不会。你知道 Hotspot VM 或 OpenJDK VM 的作用吗?其次,在加载类和初始化类时有什么区别吗?我之所以问,是因为我链接的文章说所描述的习语将适用于任何实现,但我不太确定,因为正如你所描述的,它可能依赖于 VM。
    • 澄清我所说的“类加载是否在类加载器中确定”:我的意思是当类加载器加载一个类时,它是否看到它拥有的类(通过符号引用)以前从未见过并尝试加载它,还是在实际需要时决定在执行引擎中加载一个类?
    • 首先最重要的是,所描述的习惯用法与所有JVM兼容,因为它只依赖于精确指定的初始化顺序,加载时间无关紧要。如果类文件的存在发生更改,即如果您同时删除或创建类文件,加载时间可能会有所不同。对于普通程序,这无关紧要。类加载器实现通常没有影响,因为它们所做的只是定位和读取类文件字节并将它们传递给defineClass 方法之一。从那里开始,JVM 实现接管。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 2013-02-27
    相关资源
    最近更新 更多