JDK-6967533 : ExceptionInInitializerError on systems with uninitialized clock
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2010-07-08
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
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 7
7 b102Fixed
Description
The System class uses methods to set the static in/out/err fields to null initially (the fields are later set to their correct values), and for reasons now lost in the history of Java perform a check that was assumed to be vacuously true, that:

 currentTimeMillis() >= 0

however if the system time has not been initialized (or is deliberately set far in the past) the result can be negative which results in the code explicitly throwing NullPointerException which leads to ExceptionInInitializerError which prevents the VM from initializing.

See email discussion:

http://mail.openjdk.java.net/pipermail/core-libs-dev/2010-July/004549.html

Problem reported by jon.vanalten at redhat.com

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/tl/jdk/rev/da8526047e5f
11-07-2010

SUGGESTED FIX http://cr.openjdk.java.net/~martin/webrevs/openjdk7/TimeTravel/ *** 67,77 **** * The "standard" input stream. This stream is already * open and ready to supply input data. Typically this stream * corresponds to keyboard input or another input source specified by * the host environment or user. */ ! public final static InputStream in = nullInputStream(); /** * The "standard" output stream. This stream is already * open and ready to accept output data. Typically this stream * corresponds to display output or another output destination --- 67,77 ---- * The "standard" input stream. This stream is already * open and ready to supply input data. Typically this stream * corresponds to keyboard input or another input source specified by * the host environment or user. */ ! public final static InputStream in = null; /** * The "standard" output stream. This stream is already * open and ready to accept output data. Typically this stream * corresponds to display output or another output destination *** 94,104 **** * @see java.io.PrintStream#println(int) * @see java.io.PrintStream#println(long) * @see java.io.PrintStream#println(java.lang.Object) * @see java.io.PrintStream#println(java.lang.String) */ ! public final static PrintStream out = nullPrintStream(); /** * The "standard" error output stream. This stream is already * open and ready to accept output data. * <p> --- 94,104 ---- * @see java.io.PrintStream#println(int) * @see java.io.PrintStream#println(long) * @see java.io.PrintStream#println(java.lang.Object) * @see java.io.PrintStream#println(java.lang.String) */ ! public final static PrintStream out = null; /** * The "standard" error output stream. This stream is already * open and ready to accept output data. * <p> *** 108,118 **** * or other information that should come to the immediate attention * of a user even if the principal output stream, the value of the * variable <code>out</code>, has been redirected to a file or other * destination that is typically not continuously monitored. */ ! public final static PrintStream err = nullPrintStream(); /* The security manager for the system. */ private static volatile SecurityManager security = null; --- 108,118 ---- * or other information that should come to the immediate attention * of a user even if the principal output stream, the value of the * variable <code>out</code>, has been redirected to a file or other * destination that is typically not continuously monitored. */ ! public final static PrintStream err = null; /* The security manager for the system. */ private static volatile SecurityManager security = null; *** 1091,1120 **** * @since 1.2 */ public static native String mapLibraryName(String libname); /** - * The following two methods exist because in, out, and err must be - * initialized to null. The compiler, however, cannot be permitted to - * inline access to them, since they are later set to more sensible values - * by initializeSystemClass(). - */ - private static InputStream nullInputStream() throws NullPointerException { - if (currentTimeMillis() > 0) { - return null; - } - throw new NullPointerException(); - } - - private static PrintStream nullPrintStream() throws NullPointerException { - if (currentTimeMillis() > 0) { - return null; - } - throw new NullPointerException(); - } - - /** * Initialize the system class. Called after thread initialization. */ private static void initializeSystemClass() { props = new Properties(); initProperties(props); --- 1091,1100 ----
08-07-2010

EVALUATION There is no reason that currentTimeMillis() must return a value >= 0, but further there seems to be no present-day reason to employ this "anti-inlining" trick in the first place. There seems to be no reason that the in/out/err fields can not be set directly to null without use of an initialization method.
08-07-2010