Irina’s Weblog

24/7/2017

Under the hood: assert in Java

Filed under: Daily — Izida @ 6:12 pm

How does pre-Java8 compilers/JVMs handle assert? It is not a function, it is a keyword instead, and has a special semantics of executing its test only if asserts are allowed in the JVM (JVM flag “-ea”).

My goal is to create a simple Java assertFunc() method, which like the assert keyword acts only when the -ea flag of the JVM is set, generates the same error when assertion fails and does nothing in case the assertion are disabled at runtime.

First let’s analyze what Java bytecode is generated when asserts are used. The following simple Java class would suffice our needs:

The System.out’s are there to show the deferred execution of the message concatenation – the second getMax() is only called if the condition of the assert fails (for test – change i to 1). If you run the program with “-ea” VM flag, only then the code for the assert (and the calculation of its arguments) gets executed.

What happens under the hood can be understood by looking at the decompiled byte code:

Here we see that once the compiler sees the “assert” keyword in a class, it generates a static final boolean field (“$assertionsDisabled”) which holds the negated value of Class.desiredAssertionStatus() method call.

How is this field used? We need to look at the main() method itself:

The main() starts with the assertion flag check – if assertions are disabled (flag is true), a jump (instruction 6) is made to the line just after the assert statement, this way skipping the test. The statement after the assert in this case is the return statement (instruction 45). If assertions are enabled, the getMax() function is called and the test gets executed. If the test fails, a java.lang.AssertionError with the given message is created and thrown, calling getMax() for the second time.

A possible Java 8 equivalent is:

I have introduced lambdas for the parameters of the assertFunc to take advantage of the deferred execution. If I simply expected a boolean and a string as parameters to the function assertFunc(), they would always get calculated – even if the asserts were disabled.

Conclusion: Assertions in Java are always present in the bytecode (.class file) and modify the structure of the classes that use them.

п»ї