What does the Java assert keyword do, and when should it be used?

前端 未结 19 1537
眼角桃花
眼角桃花 2020-11-22 15:58

What are some real life examples to understand the key role of assertions?

19条回答
  •  太阳男子
    2020-11-22 16:34

    What does the assert keyword in Java do?

    Let's look at the compiled bytecode.

    We will conclude that:

    public class Assert {
        public static void main(String[] args) {
            assert System.currentTimeMillis() == 0L;
        }
    }
    

    generates almost the exact same bytecode as:

    public class Assert {
        static final boolean $assertionsDisabled =
            !Assert.class.desiredAssertionStatus();
        public static void main(String[] args) {
            if (!$assertionsDisabled) {
                if (System.currentTimeMillis() != 0L) {
                    throw new AssertionError();
                }
            }
        }
    }
    

    where Assert.class.desiredAssertionStatus() is true when -ea is passed on the command line, and false otherwise.

    We use System.currentTimeMillis() to ensure that it won't get optimized away (assert true; did).

    The synthetic field is generated so that Java only needs to call Assert.class.desiredAssertionStatus() once at load time, and it then caches the result there. See also: What is the meaning of "static synthetic"?

    We can verify that with:

    javac Assert.java
    javap -c -constants -private -verbose Assert.class
    

    With Oracle JDK 1.8.0_45, a synthetic static field was generated (see also: What is the meaning of "static synthetic"?):

    static final boolean $assertionsDisabled;
      descriptor: Z
      flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
    

    together with a static initializer:

     0: ldc           #6                  // class Assert
     2: invokevirtual #7                  // Method java/lang Class.desiredAssertionStatus:()Z
     5: ifne          12
     8: iconst_1
     9: goto          13
    12: iconst_0
    13: putstatic     #2                  // Field $assertionsDisabled:Z
    16: return
    

    and the main method is:

     0: getstatic     #2                  // Field $assertionsDisabled:Z
     3: ifne          22
     6: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
     9: lconst_0
    10: lcmp
    11: ifeq          22
    14: new           #4                  // class java/lang/AssertionError
    17: dup
    18: invokespecial #5                  // Method java/lang/AssertionError."":()V
    21: athrow
    22: return
    

    We conclude that:

    • there is no bytecode level support for assert: it is a Java language concept
    • assert could be emulated pretty well with system properties -Pcom.me.assert=true to replace -ea on the command line, and a throw new AssertionError().

提交回复
热议问题