JDK-8043189 : 12.4.1: Should asserts trigger initialization of outer classes?
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 8
  • Priority: P5
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2014-05-14
  • Updated: 2016-09-27
  • Resolved: 2016-09-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Fixed
Related Reports
Relates :  
Description
Since JLS 3, 12.4.1 has included a rule for performing static initialization of top-level classes when an assert statement is executed:

"T is a top-level class, and an assert statement (��14.10) lexically nested within T is executed."

I am unable to reproduce this behavior:

-----
public class AssertInClass {
   public static final java.io.PrintStream s = System.out.printf("initializing\n");

   public static class C {

       public void foo() { assert System.out.printf("foo assert\n") != null; }

       public static void main(String... args) {
           assert System.out.printf("main assert\n") != null;
           new C().foo();
           //new AssertInClass(); // uncommenting triggers initialization
           System.out.println("done");
       }
   }

}

$ -> java7 -ea AssertInClass\$C
main assert
foo assert
done
// initialization never happens
-----

JVMS 5.5 does not directly account for this circumstance, so I assume the JLS rule was written with a certain implementation strategy in mind that would require some sort of access to the (initialized) outer class.  It appears that this implementation strategy is not used, and perhaps never was.

I'd appreciate better historical context, but from what I can tell, it looks like this rule is simply wrong and should be removed.
Comments
The assumption in the Description is correct -- JLS3 14.10 was specified to align with a javac implementation strategy that was never used, i.e. "An assert statement causes the enclosing top level class (if it exists) to be initialized, if it has not already been initialized (12.4.1)." Matters were clarified in JLS7 but the stray assert-causes-initialization clause remained in 12.4.1.
2015-09-23