JIT 优化防止技术

3
在Java 8源代码中,我们可以找到在Class类内部实现的JIT优化方法。
/*
 * Private constructor. Only the Java Virtual Machine creates Class objects.
 * This constructor is not used and prevents the default constructor being
 * generated.
 */
private Class(ClassLoader loader) {
    // Initialize final field for classLoader.  The initialization value of non-null
    // prevents future JIT optimizations from assuming this final field is null.
    classLoader = loader;
}

所以,这个构造函数从未被调用,但JIT将通过这个技巧“欺骗”。

我的问题是:它是否可以以稍微不同的方式实现,比如说

private Class() {
    classLoader = (ClassLoader)(new Object());
}

这是毫无意义的逻辑,但是如果构造函数永远不会被调用,那有什么关系呢?

这种技巧是否也可以防止JIT进行优化?


我无法想象它会用于任何非本地代码,特别是因为它不是类型安全的构造函数。 - Makoto
@Makoto 你是指 classLoader 字段吗? - Andremoniy
不,我的意思是这个私有构造函数。我在任何Java库中都找不到它的用途,并且我怀疑我们这些凡人不想使用它,因为它不是类型安全的“Class”实例。请记住:“Class”被定义为“Class <T>”。 - Makoto
抱歉,但这个事实与我的问题有什么关系吗?我正在询问有关JIT优化如何防止工作的方法。 - Andremoniy
好的,我将删除关于“volatile”的部分问题,这似乎有点愚蠢。 - Andremoniy
对所有感兴趣的人,我已经大幅修改了我的问题,强调了有关JIT优化防止的主要问题。 - Andremoniy
2个回答

5
在 Java 6、Java 7(以及 Java 8 更新版本 40 之前),构造函数只需要简单地写成 private Class() {},但是在这些版本中,没有 classLoader 字段。这意味着 ClassClassLoader 之间的关联必须以一种特殊的 JVM 方式维护,因此,getClassLoader() 必须调用一个 native 方法,不一定涉及 JNI,而是处理为 JVM 内部操作,但仍需要 JVM 本地代码内部的特殊注意。此外,垃圾回收器也必须知道这种特殊关系。
相比之下,在反射中隐藏一个字段并不那么复杂,而现在有了普通字段,可以简化 JVM 的本地代码,尤其是 getClassLoader() 操作和垃圾回收器的实现。如果它是一个普通字段,优化器也可能更容易地将字段访问内联化。
现在,当通过特殊的 JVM 代码创建 Class 对象时,这可能与优化 JIT 分析构造函数的实际代码以预测该 final 字段的可能值的假设条件相矛盾。
请注意,没有人说当前的 JIT 是那么聪明。该注释谈论了假设的“未来 JIT 优化”。使用构造函数初始化该字段的参数值符合 JVM 的实际操作。
相比之下,像您建议的 classLoader = (ClassLoader)(new Object()); 这样的构造函数可能会导致一个假定的优化器得出结论,即该字段不能用实际的 ClassLoader 实例进行初始化,因为该代码永远无法正常完成。

1
似乎早期版本的Java 8也没有classLoader字段。它使用了一个native方法。 - 4castle
1
@4castle:看起来它确实是在更新40中添加的。 - Holger

0

Class 的源代码中的注释指出,初始化值可以让未来的 JIT 优化“知道 classLoader 字段不为 null”,因此优化器在未来可能会做得更好。

要防止优化,只需将字段声明为 volatile


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接