本文介绍了如何在Sun的JVM中禁用延迟类加载/初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

默认情况下,Sun的JVM会延迟加载类和延迟初始化(即调用中抛出异常 code>阻止。

By default, Sun's JVM both lazily loads classes and lazily initializes (i.e. calls their <clinit> methods) them. Consider the following class, ClinitBomb, which throws an Exception during a static{} block.

public class ClinitBomb {
    static {
        explode();
    }
    private static void explode() {
        throw new RuntimeException("boom!");
    }
}

现在,考虑如何触发炸弹: p>

Now, consider how to trigger the bomb:

public class Main {
    public static void main(String[] args) {
        System.out.println("A");
        try {
            Class.forName("ClinitBomb");
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        System.out.println("B");
        ClinitBomb o2 = new ClinitBomb();
        System.out.println("C");
    }
}



我们保证爆炸发生在B点之前,因为 forName 的文档说如此;问题是它是否发生在A点之前(当 Main 加载时)。在Sun的JVM中,即使 main()包含对 ClinitBomb 的静态引用,它发生在A之后。

We're guaranteed the explosion happens before point B, since forName's documentation says so; the question is whether it happens before point A (when Main is loaded.) In Sun's JVM, even though main() contains a static reference to ClinitBomb, it happens after A.

我想要一种方法来告诉JVM加载并初始化 ClinitBomb (因此炸弹在点之前爆炸 一般来说,我想要一个方法说,每当加载/初始化类X,也为任何类Y它引用。

I want a way to tell the JVM to load and initialize ClinitBomb as soon as it initializes Main (so the bomb explodes before point A.) In general, I want a way to say, "whenever loading/initializing class X, also do so for any classes Y it references."

推荐答案

没有办法做到这一点。 JLS在说(强调我):

There is no way to do this. The JLS says, in §12.4.1 When Initialization Occurs (emphasis mine):

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


  • T是一个类,创建了一个T实例。

  • T是一个类和一个静态

  • 使用由T声明的静态字段,并且该字段是由T声明的方法。不是常数变量(§4.12.4)。

  • T是一个顶级类,并且执行在T中词法嵌套的assert语句(§14.10)。

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the field is not a constant variable (§4.12.4).
  • T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.

在类Class和package java.lang.reflect中调用某些反射方法也会导致类或接口初始化。 类别或介面不会在任何其他情况下初始化

Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.

虽然你可以做的是使用JVM 编写添加了一个静态块到每个类,显式初始化它的引用类(通过Class.forName,可能)。一旦一个类被初始化,从它可达到的所有类都将被初始化。这可能会给你的结果,你后。这是相当多的工作,但!!

Although what you could do would be to use the JVM instrumentation API to write a ClassFileTransformer which added a static block to every class which explicitly initialized its referenced classes (via Class.forName, probably). As soon as one class gets initialized, all the classes reachable from it will be initialized. That might give you the result you're after. It's quite a lot of work, though!

这篇关于如何在Sun的JVM中禁用延迟类加载/初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-12 07:58