【问题标题】:Java assert nasty side-effect - compiler bug?Java断言讨厌的副作用 - 编译器错误?
【发布时间】:2010-02-17 10:59:38
【问题描述】:

这个

public class test 
{
    public static void main(String[] args) 
    {
        Object o = null;
        assert o != null;
        if(o != null)
          System.out.println("o != null");
    }
}

打印出 "o != null"; 1.5_22 和 1.6_18。编译器错误?注释掉断言修复它。当断言被禁用时,字节码似乎直接跳转到打印语句:

 public static main(String[]) : void
   L0
    LINENUMBER 5 L0
    ACONST_NULL
    ASTORE 1
   L1
    LINENUMBER 6 L1
    GETSTATIC test.$assertionsDisabled : boolean
    IFNE L2
    ALOAD 1: o
    IFNONNULL L2
    NEW AssertionError
    DUP
    INVOKESPECIAL AssertionError.<init>() : void
    ATHROW
   L2
    LINENUMBER 8 L2
    GETSTATIC System.out : PrintStream
    LDC "o != null"
    INVOKEVIRTUAL PrintStream.println(String) : void
   L3
    LINENUMBER 9 L3
    RETURN
   L4

【问题讨论】:

  • 这里不打印任何东西,1.6.0_12
  • 你是用哪个版本的javac编译器编译的?它应该是一个编译器错误,使用 1.6.0_18(windows 32 位)编译代码按预期工作(不打印 o!= null)。
  • 不可重现。您确定这正是您的测试代码吗?你用的是什么编译器和什么jvm?什么标志?
  • Windows 7 x64 位。将重新测试 x32 ...
  • 也许你应该澄清你的问题并提到这发生在 ecj(Java 的 Eclipse 编译器)而不是 Sun 的 javac。顺便说一句,它适用于我的 Galileo(和 Java 6u18)。

标签: java eclipse compiler-construction assert


【解决方案1】:

我不知道“讨厌”。你能举一个真实的例子来说明这会咬你的一些代码吗?你的例子看起来很做作。

编辑 - 出于好奇,我输入了程序,编译并使用 java 1.6.0_16 运行它。对我来说没有明显的编译器错误:

  • 启用断言 (java -ea test) 我得到一个断言错误。
  • 禁用断言(java 测试)我得到 no 输出。

【讨论】:

  • 我认为任何使编译器生成的代码默默地做错事的错误都是“讨厌的”。 (如果编译器实际上未能编译此类代码,则编译器错误会更小——那么至少你知道出了点问题。)
  • 感谢测试。刚刚尝试过,对我来说 jdk1.6.0_18 也不会发生。现在我只需要弄清楚 Eclipse 构建它的方式有什么不同...
  • @Alex Eclipse 有自己的编译器。
【解决方案2】:

可以在运行时启用和禁用断言。如果您使用 -ea-switch(用于启用断言)执行代码,则断言应该可以工作:

java -ea my.class

【讨论】:

    【解决方案3】:

    JVM 正在优化 if (o != null) 子句,因为您已经断言 o 永远不会为空。

    在运行时默认情况下不启用断言,通常用于验证代码是否满足某些约定,例如您只想确保某个对象永远不会为空(例如,避免空指针异常)。正是因为这个“契约”,编译器才可以优化 if (o != null),因为它知道这种情况永远不会发生。

    由于它们通常不会在运行时启用,因此请将它们视为有助于开发一段代码而不是运行时错误检查机制。

    【讨论】:

    • 您能否指出 JLS 中指出编译器在优化时可能假定断言为真的部分?
    • 不。结合无法复制行为的其他答案以及我自己没有尝试过的事实,我很想相信它可能是编译器错误,但可能是一些过度优化的原因......
    • 考虑到代码仅在使用 Eclipse 编译器构建时才会出现,也许 Eclipse 编译器正在优化 if 语句?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多