Java 2 SDK for Solaris Developer's Guide

Design FAQ

Following is a collection of frequently asked questions concerning the design of the assertion facility.

Design FAQ - General Questions

  1. Why provide an assertion facility at all, given that one can program assertions atop the Java programming language with no special support?

    Although ad hoc implementations are possible, they are of necessity either ugly (requiring an if statement for each assertion) or inefficient (evaluating the condition even if assertions are disabled). Further, each ad hoc implementation has its own means of enabling and disabling assertions, which lessens the utility of these implementations, especially for debugging in the field. As a result of these shortcomings, assertions have never become a part of the Java culture. Adding assertion support to the platform stands a good chance of rectifying this situation.

  2. Why does this facility justify a language change, as opposed to a library solution?

    We recognize that a language change is a serious effort, not to be undertaken lightly. The library approach was considered. It was, however, deemed essential that the runtime cost of assertions be negligible if they are disabled. In order to achieve this with a library, the programmer is forced to hard-code each assertion as an if statement. Many programmers would not do this. Either they would omit the if statement and performance would suffer, or they would ignore the facility entirely. Note also that assertions were contained in James Gosling's original specification for Java. Assertions were removed from the Oak specification because time constraints prevented a satisfactory design and implementation.

  3. Why not provide a full-fledged design-by-contract facility with preconditions, postconditions and class invariants, like the one in the Eiffel programming language?

    We considered providing such a facility, but were unable to convince ourselves that it is possible to graft it onto the Java programming language without massive changes to the Java platform libraries, and massive inconsistencies between old and new libraries. Further, we were not convinced that such a facility would preserve the simplicity that is Java's hallmark. On balance, we came to the conclusion that a simple boolean assertion facility was a fairly straight-forward solution and far less risky. It's worth noting that adding a boolean assertion facility to the language doesn't preclude adding a full-fledged design-by-contract facility at some time in the future.

    The simple assertion facility does enable a limited form of design-by-contract style programming. The assert statement is appropriate for postcondition and class invariant checking. Precondition checking should still be performed by checks inside methods that result in particular, documented exceptions, such as IllegalArgumentException and IllegalStateException.

  4. In addition to boolean assertions, why not provide an assert-like construct to suppress the execution of an entire block of code if assertions are disabled?

    Providing such a construct would encourage programmers to put complex assertions inline, when they are better relegated to separate methods.

Design FAQ - Compatibility

  1. Won't the new keyword cause compatibility problems with existing programs that use assert as an identifier?

    Yes, for source files. (Binaries for classes that use assert as an identifier will continue to work fine.) To ease the transition, we describe a strategy whereby developers can continue using assert as an identifier during a transitional period. See Source Compatibility.

Design FAQ - Syntax and Semantics

  1. Why allow primitive types in Expression2?

    There is no compelling reason to restrict the type of this expression. Allowing arbitrary types provides convenience for developers who for example want to associate a unique integer code with each assertion. Further, it makes this expression seem like System.out.print(...), which is desirable.

Design FAQ - The AssertionError Class

  1. When an AssertionError is generated by an assert statement in which Expression2 is absent, why isn't the program text of the asserted condition used as the detail message (e.g., "height < maxHeight")?

    While doing so might improve out-of-the-box usefulness of assertions in some cases, the benefit doesn't justify the cost of adding all those string constants to .class files and runtime images.

  2. Why doesn't an AssertionError allow access to the object that generated it? Similarly, why not pass an arbitrary object from the assertion to the AssertionError in place of a detail message?

    Access to these objects would encourage programmers to attempt to recover from assertion failures, which defeats the purpose of the facility.

  3. Why not provide context accessors (like getFile, getLine, getMethod) on AssertionError?

    This facility is best provided on Throwable, so it may be used for all throwables, and not just assertion errors. We intend to enhance Throwable to provide this functionality in the same release in which the assertion facility first appears.

  4. Why is AssertionError a subclass of Error rather than RuntimeException?

    This issue was controversial. The expert group discussed it at length, and came to the conclusion that Error was more appropriate to discourage programmers from attempting to recover from assertion failures. It is, in general, difficult or impossible to localize the source of an assertion failure. Such a failure indicates that the program is operating "outside of known space," and attempts to continue execution are likely to be harmful. Further, convention dictates that methods specify most runtime exceptions they may throw (via "@throws" doc comments). It makes little sense to include in a method's specification the circumstances under which it may generate an assertion failure. Such information may be regarded as an implementation detail, which can change from implementation to implementation and release to release.

Design FAQ - Enabling and Disabling Assertions

  1. Why not provide a compiler flag to completely eliminate assertions from object files?

    It is a firm requirement that it be possible to enable assertions in the field, for enhanced serviceability. It would have been possible to also permit developers to eliminate assertions from object files at compile time. However, since assertions can contain side effects (though they should not), such a flag could alter the behavior of a program in significant ways. It is viewed as good thing that there is only one semantics associated with each valid Java program. Also, we want to encourage users to leave asserts in object files so they can be enabled in the field. Finally, the standard Java "conditional compilation idiom" described in JLS 14.19 can be used to achieve this effect for developers who really want it.

  2. Why does setPackageAssertionStatus have package-tree semantics instead of the more obvious package semantics?

    Hierarchical control is useful, as programmers really do use package hierarchies to organize their code. For example, package-tree semantics allow assertions to be enabled or disabled in all of Swing at one time.

  3. Why does setClassAssertionStatus return a boolean instead of throwing an exception if it is invoked when it's too late to set the assertion status (i.e., the named class has already been loaded)?

    No action (other than perhaps a warning message) is necessary or desirable if it's too late to set the assertion status. An exception seems unduly heavyweight.

  4. Why not overload a single method to take the place of setDefaultAssertionStatus and setAssertionStatus?

    Clarity in method naming is for the greater good.

  5. Why is there no RuntimePermission to prevent applets from enabling/disabling assertions?

    While applets have no reason to call any of the ClassLoader methods for modifying assertion status, allowing them to do so seems harmless. At worst, an applet can mount a weak denial-of-service attack by turning on asserts in classes that have yet to be loaded. Moreover, applets can only affect the assert status of classes that are to be loaded by class loaders that the applets can access. There already exists a RuntimePermission to prevent untrusted code from gaining access to class loaders (getClassLoader).

  6. Why not provide a construct to query the assert status of the containing class?

    Such a construct would encourage people to inline complex assertion code, which we view as a bad thing:


               if (assertsEnabled()) {
                   ...
               }

    Further, it is straightforward to query the assert status atop the current API, if you feel you must:


     boolean assertsEnabled = false;
              assert assertsEnabled = true;  // Intentional side-effect!!!
              // Now assertsEnabled is set to the correct value