代码之家  ›  专栏  ›  技术社区  ›  Thimmayya

在JVM中加载类时,类的不同部分以什么顺序初始化?

  •  6
  • Thimmayya  · 技术社区  · 16 年前

    想象一个Java类,它具有在类中可以找到的大多数特性。例如:它从另一个类继承,实现了几个接口,包括一些“静态最终”常量、一些最终常量、一些静态变量、实例变量、一个静态块、一个未命名的代码块(只是{}中的代码)、构造函数、方法等。

    这要回到Java的绝对基础/内部,但我还没有找到一篇好文章来解释正确的顺序。

    2 回复  |  直到 16 年前
        1
  •  1
  •   toolkit    16 年前

    这个怎么样 JLS

        2
  •  4
  •   VonC    12 年前

    这可以在本节中描述 2.17.4 of the JVMS 5.0/6

    2.17.4初始化

    类的初始化包括:

    • 类中声明的静态字段(§2.9.2)的初始值设定项。

    接口初始化包括对接口中声明的字段执行初始化器(§2.13.3.1)。

    类或接口类型T将在发生以下情况之一之前立即初始化:

    • T是一个类,调用了T的静态方法。
    • 使用或指定了一个T的非恒定静态场。常量字段是(显式或隐式)最终和静态字段,并用编译时常量表达式的值初始化。对此类字段的引用必须在编译时解析为编译时常量值的副本,因此使用此类字段不会导致初始化。

    这里的目的是一个类型有一组初始值设定项,使其处于一致状态,并且该状态是其他类观察到的第一个状态。静态初始值设定项和类变量初始值设定项是按文本顺序执行的,并且可能不会引用在类中声明的类变量,这些类变量的声明在使用后以文本形式出现,即使这些类变量在范围内。此限制旨在在编译时检测大多数循环初始化或其他格式错误的初始化。

    在初始化一个类或接口之前,如果它以前没有被初始化过,则初始化它的超类。


    的更新版本 Initialization in JVMS 8 is in Chapter 5.5

    类或接口的初始化包括执行其类或接口初始化方法( §2.9 ).

    类或接口只能在以下情况下初始化:

    • 执行任何一条Java虚拟机指令 new , getstatic putstatic invokestatic 引用类或接口的( §new §getstatic §putstatic , §invokestatic
      所有这些指令都通过字段引用或方法引用直接或间接引用类。
      在执行新指令时,如果引用的类或接口尚未初始化,则初始化该类或接口。
      一经执行 静止 , 腐败 不动产 指令,如果尚未初始化,则声明已解析字段或方法的类或接口将被初始化。
    • java.lang.invoke.MethodHandle §5.4.3.5 REF_getStatic ), 4 ( REF_putStatic ), 6 ( REF_invokeStatic ),或8( REF_newInvokeSpecial ).
    • 在类库中调用某些反射方法( §2.12 Class 还是打包 java.lang.reflect
    • 它被指定为Java虚拟机启动时的初始类( §5.2 ).

    .

    因为Java虚拟机是多线程的,所以类或接口的初始化需要仔细的同步,因为其他一些线程可能会试图同时初始化相同的类或接口。

    Java虚拟机的实现负责使用以下过程进行同步和递归初始化。
    它假设 等级 对象已经过验证和准备,并且 等级

    • 等级
    • 对象正在由某个特定线程初始化。
    • 等级 对象已完全初始化并准备好使用。
    • 等级 对象处于错误状态,可能是因为尝试初始化但失败。