Java: Assertions

Assertions stop program when "impossible" situations are detected

Impossible conditions. Program debugging is filled with "impossible" problems ("But that parameter can't possibly be null here"). If you're lucky, the problem is detected immediately in some way you can easily diagnose. If not, the error may propogate thru the program, finally crashing, but so far from the original bug that diagnosis is difficult. Even worse, the bug may not produce visible symptoms until after it has altered permanent data. Assert statements provide an easy means of checking for impossible conditions, with little or no runtime cost.

Programmer, not user problems. The purpose or asserts is to detect programming errors, and they should not be used in the case of erroneous user input or actions.

Crash as quickly as possible. Discovering bugs as early as possible is good. Every program starts with bugs, and the debugging process is faster and simpler when the bugs are detected early. It's better to discover a problem at compile time than at run time, and it's better to discover a run-time bug as early as possible. Often a run-time bug doesn't cause an immediate, visible, disaster. Instead, the consequences of the bug distort the following execution, and the bad effects may not become visible for a long time. The crippled program may corrupt files or have other bad consequences. Tracing symptoms back to the orginal cause can be a long, tedious process. The goal is to detect bugs as early as possible. Assertions provide a relatively painless way to stop many bugs before they go too far.

Two forms of the assert statement.

Usual form

An assert statement has two parts separated by a colon. The boolean condition must be true for execution to continue. If it is false, an AssertionError is thrown, which terminates execution and display the message string. Some examples.

assert jobQueue.size() == 0 : "processB: queue should have been empty.";

assert connector != null : "merge: Connector null for " + rel;

When asserts are enabled (more on that below), the assert statement checks the condition (queue empty, connector is not null, etc) which must be true for the program to function correctly.. If it's true, execution continues. If it's null, an exception containing the message is thrown. This message is for the programmer, so it doesn't have to be user friendly. I typically include the name of the method and sometimes other information that will help make sense of the error.

Abbreviated form

The simplest form the assert statement specifies only a boolean expression that must be true. This is ok when there's not much to say, or the likelyhood of failing seems so remote it isn't worth the extra typing.

assert n > 0;

Enabling assertions at runtime

Assertion checking defaults to off at runtime, unfortunately. You should always turn them on.

JVM runtime -enableassertions (-ea) option

CommandEffect
java MyProgAssert statements are removed by class loader.
java -enableassertions MyProgAssert statements are executed.
java -ea MyProgShort form for allowing assertions.

It's also possible to enable/disable assertion checking at runtime for individual classes or for library routines, but that level of control is not useful for most purposes.

Turning runtime assertion checking on in NetBeans 4.0

See NetBeans IDE.

Should runtime assertion checking default on?

  1. Some argue that a production program should not have the overhead of evaluating asserts. Asserts are not slow, but there is some cost. If they are not turned on at at execution time, the class loader actually strips out all the assertion code so they really don't take up any time or memory. But this small amount of time is surely unnoticeable in all but the most critical tasks.
  2. The user may be presented with an unfamiliar error message. This seems like an especially bad argument. Does the user really prefer bad results to a strange error message?

Why don't the same people that want assertion checking to default off also want subscript checking to default off?

Example

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
/** AssertTest.java - test assertions.
 * @author Fred Swartz
 * @version 1.00 2004-04-04
 *    Compile: javac -source 1.4 AssertTest.java
 *    Run    : java -ea AssertTest
 */

class AssertTest {
    //=========================================================== main
    public static void main(String[] args) {
        // The following assert statement will stop execution
        //     with a message if assertions are turned on.
        assert false : "Assertions are turned on.";
        
        // The following statement will only be printed if 
        //     assertions are turned off because  assertions
        //     were not allowed at run time by the -ea parameter.
        System.out.println("Assertions are not active.");
    }//end main
}//end class AssertTest

More philosophy -- needs to be rewritten

Test for consistency

One path to early bug detection is to test variables to see if they have expected values. If something is wrong, the program can stop and indicate that an unexpected inconsistency was discovered. Later, when the program is released, this checking may either be disabled to increase speed, or left in if a "crash" is better than uncontrolled bug propogation (usually the case). If the checking code is removed or disabled, it should be reinserted or activated during testing all future updates. Writing checking code can be a major headache, so it isn't done in many cases. The assert statement makes testing conditions relatively easy, and allows easy activation or deactivation of some or all of the checking code.

Check for "impossible" conditions, not bad input

assert shouldn't be used for checking for bad input. Input should be checked by code that gives the user a meaningful response and perhaps a chance to correct the input.

Assertions are used to check for things that can't possibly be wrong! This is what bugs are -- things that shouldn't happen do happen because there is something wrong with the code. Assertions are often used in the following cases.

Assertions in Java 1.4

Java 1.4 default compiler option is no assertions

The assert statement was added to Java in version 1.4. The addition of the assert keyword may invalidate a few older programs which used it as an identifier. To preserve backward compatibility the assert statement can't be used unless an option is specified the compilation (javac) commands for the JDK. Java 1.5/5 removed this restriction.

SDK 1.4 compiler option -source 1.4

CommandEffect
javac MyProg.javaNo assert statements allowed.
javac -source 1.4 MyProg.javaAssertions allowed.

NetBeans 3.6: Enabling Assertions (Java version 1.4 source)

Enabling assertions for the NetBeans compiler

  1. Choose Tools > Options menu item.
  2. Open Building > Compiler Types > External Compilation option panel.
  3. Check the Enable JDK 1.4 Source property.
  4. Repeat the above for the Internal Compilation option panel.

Enabling assertions for the NetBeans executor

  1. Choose Tools > Options menu item.
  2. Open Debugging and Execution > Execution Types > External Execution option panel.
  3. Check the Expert > Enable asserts property.