为什么 Eclipse Java 编译器检查 null 类型转换?

发布于 2024-12-06 18:02:26 字数 1375 浏览 5 评论 0原文

考虑以下 Java 代码片段:

public class Test {
    public static void use(Object[] x) {
    }

    public static void main(String[] args) {
        Object[] x = null;

        use(x);
    }
}

Eclipse 3.7 编译器为 main() 生成的 Java 字节码如下所示:

public static void main(java.lang.String[]);
  Code:
   0:   aconst_null
   1:   checkcast   #20; //class "[Ljava/lang/Object;"
   4:   astore_1
   5:   aload_1
   6:   invokestatic    #21; //Method use:([Ljava/lang/Object;)V
   9:   return

相反,这是 OpenJDK 1.6.0b22 编译器生成的字节码:

public static void main(java.lang.String[]);
  Code:
   0:   aconst_null
   1:   astore_1
   2:   aload_1
   3:   invokestatic    #2; //Method use:([Ljava/lang/Object;)V
   6:   return

请注意Eclipse 编译器发出额外的 checkcast 操作码。它似乎也只适用于数组,而不适用于任何其他变量类型。

我的问题:

  1. 据我所知,null 可以分配给任何类,包括数组。 checkcast 一个已知的 null 值是否有意义?

  2. 额外的checkcast会影响性能吗?

  3. 这是否可以被视为 Eclipse Java 编译器中的错误?

注意:

我可以部分回答(2),至少就 OpenJDK 1.6.0b22 JVM 而言。我执行了一个简单的基准测试,在定时紧密循环中对 null 进行了多次赋值。我无法检测到任何一致的性能差异,无论是哪种方式。

也就是说,我的基准测试非常简单,任何半点优化器都可能使其毫无用处,因此它可能并不代表现实世界的应用程序。我希望 JVM总是优化该 checkcast 操作码,但情况可能并非如此。

Consider the following Java snippet:

public class Test {
    public static void use(Object[] x) {
    }

    public static void main(String[] args) {
        Object[] x = null;

        use(x);
    }
}

The Java bytecode produced for main() by the Eclipse 3.7 compiler looks like this:

public static void main(java.lang.String[]);
  Code:
   0:   aconst_null
   1:   checkcast   #20; //class "[Ljava/lang/Object;"
   4:   astore_1
   5:   aload_1
   6:   invokestatic    #21; //Method use:([Ljava/lang/Object;)V
   9:   return

On the contrary, this is the bytecode produced by the OpenJDK 1.6.0b22 compiler:

public static void main(java.lang.String[]);
  Code:
   0:   aconst_null
   1:   astore_1
   2:   aload_1
   3:   invokestatic    #2; //Method use:([Ljava/lang/Object;)V
   6:   return

Note that the Eclipse compiler issues an extra checkcast opcode. It also seems to do that only for arrays and not for any other variable type.

My questions:

  1. As far as I know, null is assignable to any class, including arrays. Does it make any sense at all to checkcast a known null value?

  2. Does the extra checkcast affect performance?

  3. Could this be considered a bug in the Eclipse Java compiler?

NOTE:

I can partially answer (2), at least as far as the OpenJDK 1.6.0b22 JVM is concerned. I performed a simple benchmark with several assignments to null in a timed tight loop. I could not detect any consistent performance difference, one way or the other.

That said, my benchmark was simple enough that any half-decent optimizer would have probably made it useless, so it may not be indicative of a real world application. I would expect that the JVM would always optimize out that checkcast opcode, but that may not be the case.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眉黛浅 2024-12-13 18:02:26

至于你的第一个问题,你是对的,那里的 checkcast 指令是多余的。
根据 Sun 的 Java Hotspot wiki,空检查和实例检查很便宜。

我已经在 Eclipse Bugzilla 中打开了一个问题,以获取来自 Eclipse 编译器的反馈团队,但正如之前指出的,这是多余的,但无害的检查。它仅影响字节码大小,Java HotSpot 编译器可能会在运行时应用类型检查优化。

更新:来自 Eclipse 编译器团队 这似乎是另一个老错误

As for your first question, you are right, the checkcast instruction there is redundant.
According to Sun's Java Hotspot wiki null checks and instance checks are cheap.

I've opened an issue in Eclipse Bugzilla to get feedback from Eclipse compiler team, but as it been pointed out before, it is redundant, but harmless check. It only affects the bytecode size and Java HotSpot compiler will likely apply type check optimization at the runtime.

Update: from Eclipse compiler team it seem like as side effect of another old bug.

栖迟 2024-12-13 18:02:26
  1. 不,检查没有意义,因为 null 始终可转换为任何引用类型。但它不会伤害任何东西。
  2. 无论如何,任何像样的 JIT 都会优化检查(它实际上是无操作),因此最大的成本是指令占用的三个字节。
  3. 我不认为它是一个“错误”,因为生成的字节码按预期工作——它永远不会触发 ClassCastException,因为该值始终是已知且正确的——而且,正如您显然所见看到了,无论哪种方式都没有真正的性能差异。这是一个改进的机会,但无论如何都不会破坏。
  1. No, it doesn't make sense to check, as null is always castable to any reference type. But it doesn't hurt anything.
  2. Any decent JIT will optimize the check away anyway (it's effectively a no-op), so the biggest cost is the three bytes that the instruction takes up.
  3. I wouldn't consider it a "bug", as the generated bytecode works as intended -- it'll never trigger a ClassCastException, as the value is always known and correct -- and, as you apparently saw, there's not a real performance difference either way. It's an opportunity for improvement, but nothing that will break in any case.
抹茶夏天i‖ 2024-12-13 18:02:26

它可能与 javac 中的已知错误有关:生成的代码中不必要的检查< /em>

It might be related to a known bug in javac: Unnecessary checkcast in generated code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文