繁体   English   中英

为什么Eclipse Java编译器检查是否从null强制转换?

[英]Why does the Eclipse Java compiler check casts from null?

考虑以下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编译器中的错误吗?

注意:

至少就OpenJDK 1.6.0b22 JVM而言,我可以部分回答(2)。 我在一个时间紧的循环中执行了一个简单的基准测试,并分配了多个null 我无法检测到任何一种或另一种一致的性能差异。

就是说,我的基准测试非常简单,以至于任何一个像样的优化器都可能使它失效,因此它可能并不表示实际的应用程序。 我希望JVM 总是会优化该checkcast操作码,但事实并非如此。

  1. 不,检查没有意义,因为null始终可转换为任何引用类型。 但这没有任何伤害。
  2. 任何体面的JIT无论如何都会优化检查(实际上是无操作),因此最大的开销是指令占用的三个字节。
  3. 我不会将其视为“错误”,因为生成的字节码将按预期工作—它将永远不会触发ClassCastException ,因为该值始终是已知且正确的,并且正如您所看到的那样,没有真正的性能两种方式都不同。 这是一个改进的机会,但是在任何情况下都不会失败

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

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

更新: 从Eclipse编译器团队看来,这似乎是另一个旧bug的副作用。

它可能与javac中的一个已知错误有关: 生成的代码中不必要的检查

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM