United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6967533 ExceptionInInitializerError on systems with uninitialized clock
JDK-6967533 : ExceptionInInitializerError on systems with uninitialized clock

Details
Type:
Bug
Submit Date:
2010-07-08
Status:
Closed
Updated Date:
2011-05-18
Project Name:
JDK
Resolved Date:
2011-05-18
Component:
core-libs
OS:
generic
Sub-Component:
java.lang
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:

Related Reports

Sub Tasks

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
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 ----
                                     
2010-07-08
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.
                                     
2010-07-08
EVALUATION

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



Hardware and Software, Engineered to Work Together