      1 /*
      2  * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25
     26 package java.lang;
     27
     28 import java.io.IOException;
     29 import java.io.ObjectInputStream;
     30 import java.io.ObjectOutputStream;
     31 import java.io.ObjectStreamField;
     32
     33 /**
     34  * Signals that an unexpected exception has occurred in a static initializer.
     35  * An {@code ExceptionInInitializerError} is thrown to indicate that an
     36  * exception occurred during evaluation of a static initializer or the
     37  * initializer for a static variable.
     38  *
     39  * <p>As of release 1.4, this exception has been retrofitted to conform to
     40  * the general purpose exception-chaining mechanism.  The "saved throwable
     41  * object" that may be provided at construction time and accessed via
     42  * the {@link #getException()} method is now known as the <i>cause</i>,
     43  * and may be accessed via the {@link Throwable#getCause()} method, as well
     44  * as the aforementioned "legacy method."
     45  *
     46  * @author  Frank Yellin
     47  * @since   1.1
     48  */
     49 public class ExceptionInInitializerError extends LinkageError {
     50     /**
     51      * Use serialVersionUID from JDK 1.1.X for interoperability
     52      */
     53     @java.io.Serial
     54     private static final long serialVersionUID = 1521711792217232256L;
     55
     56     /**
     57      * Constructs an {@code ExceptionInInitializerError} with
     58      * {@code null} as its detail message string and with no saved
     59      * throwable object.
     60      * A detail message is a String that describes this particular exception.
     61      */
     62     public ExceptionInInitializerError() {
     63         initCause(null); // Disallow subsequent initCause
     64     }
     65
     66     /**
     67      * Constructs a new {@code ExceptionInInitializerError} class by
     68      * saving a reference to the {@code Throwable} object thrown for
     69      * later retrieval by the {@link #getException()} method. The detail
     70      * message string is set to {@code null}.
     71      *
     72      * @param thrown The exception thrown
     73      */
     74     public ExceptionInInitializerError(Throwable thrown) {
     75         super(null, thrown); // Disallow subsequent initCause
     76     }
     77
     78     /**
     79      * Constructs an {@code ExceptionInInitializerError} with the specified detail
     80      * message string.  A detail message is a String that describes this
     81      * particular exception. The detail message string is saved for later
     82      * retrieval by the {@link Throwable#getMessage()} method. There is no
     83      * saved throwable object.
     84      *
     85      * @param s the detail message
     86      */
     87     public ExceptionInInitializerError(String s) {
     88         super(s, null);  // Disallow subsequent initCause
     89     }
     90
     91     /**
     92      * Returns the exception that occurred during a static initialization that
     93      * caused this error to be created.
     94      *
     95      * <p>This method predates the general-purpose exception chaining facility.
     96      * The {@link Throwable#getCause()} method is now the preferred means of
     97      * obtaining this information.
     98      *
     99      * @return the saved throwable object of this
    100      *         {@code ExceptionInInitializerError}, or {@code null}
    101      *         if this {@code ExceptionInInitializerError} has no saved
    102      *         throwable object.
    103      */
    104     public Throwable getException() {
    105         return super.getCause();
    106     }
    107
    108     /**
    109      * Serializable fields for ExceptionInInitializerError.
    110      *
    111      * @serialField exception Throwable
    112      */
    113     @java.io.Serial
    114     private static final ObjectStreamField[] serialPersistentFields = {
    115         new ObjectStreamField("exception", Throwable.class)
    116     };
    117
    118     /*
    119      * Reconstitutes the ExceptionInInitializerError instance from a stream
    120      * and initialize the cause properly when deserializing from an older
    121      * version.
    122      *
    123      * The getException and getCause method returns the private "exception"
    124      * field in the older implementation and ExceptionInInitializerError::cause
    125      * was set to null.
    126      */
    127     @java.io.Serial
    128     private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    129         ObjectInputStream.GetField fields = s.readFields();
    130         Throwable exception = (Throwable) fields.get("exception", null);
    131         if (exception != null) {
    132             setCause(exception);
    133         }
    134     }
    135
    136     /*
    137      * To maintain compatibility with older implementation, write a serial
    138      * "exception" field with the cause as the value.
    139      */
    140     @java.io.Serial
    141     private void writeObject(ObjectOutputStream out) throws IOException {
    142         ObjectOutputStream.PutField fields = out.putFields();
    143         fields.put("exception", super.getCause());
    144         out.writeFields();
    145     }
    146
    147 }