1 /*
2  * Copyright (c) 1996, 2020, 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  * @author  Frank Yellin
40  * @since   1.1
41  */
42 public class ExceptionInInitializerError extends LinkageError {
43     /**
44      * Use serialVersionUID from JDK 1.1.X for interoperability
45      */
46     @java.io.Serial
47     private static final long serialVersionUID = 1521711792217232256L;
48 
49     /**
50      * Constructs an {@code ExceptionInInitializerError} with
51      * {@code null} as its detail message string and with no saved
52      * throwable object.
53      * A detail message is a String that describes this particular exception.
54      */
ExceptionInInitializerError()55     public ExceptionInInitializerError() {
56         initCause(null); // Disallow subsequent initCause
57     }
58 
59     /**
60      * Constructs a new {@code ExceptionInInitializerError} class by
61      * saving a reference to the {@code Throwable} object thrown for
62      * later retrieval by the {@link #getException()} method. The detail
63      * message string is set to {@code null}.
64      *
65      * @param thrown The exception thrown
66      */
ExceptionInInitializerError(Throwable thrown)67     public ExceptionInInitializerError(Throwable thrown) {
68         super(null, thrown); // Disallow subsequent initCause
69     }
70 
71     /**
72      * Constructs an {@code ExceptionInInitializerError} with the specified detail
73      * message string.  A detail message is a String that describes this
74      * particular exception. The detail message string is saved for later
75      * retrieval by the {@link Throwable#getMessage()} method. There is no
76      * saved throwable object.
77      *
78      * @param s the detail message
79      */
ExceptionInInitializerError(String s)80     public ExceptionInInitializerError(String s) {
81         super(s, null);  // Disallow subsequent initCause
82     }
83 
84     /**
85      * Returns the exception that occurred during a static initialization that
86      * caused this error to be created.
87      *
88      * @apiNote
89      * This method predates the general-purpose exception chaining facility.
90      * The {@link Throwable#getCause()} method is now the preferred means of
91      * obtaining this information.
92      *
93      * @return the saved throwable object of this
94      *         {@code ExceptionInInitializerError}, or {@code null}
95      *         if this {@code ExceptionInInitializerError} has no saved
96      *         throwable object.
97      */
getException()98     public Throwable getException() {
99         return super.getCause();
100     }
101 
102     /**
103      * Serializable fields for ExceptionInInitializerError.
104      *
105      * @serialField exception Throwable the exception
106      */
107     @java.io.Serial
108     private static final ObjectStreamField[] serialPersistentFields = {
109         new ObjectStreamField("exception", Throwable.class)
110     };
111 
112     /**
113      * Reconstitutes the ExceptionInInitializerError instance from a stream
114      * and initialize the cause properly when deserializing from an older
115      * version.
116      *
117      * The getException and getCause method returns the private "exception"
118      * field in the older implementation and ExceptionInInitializerError::cause
119      * was set to null.
120      *
121      * @param  s the {@code ObjectInputStream} from which data is read
122      * @throws IOException if an I/O error occurs
123      * @throws ClassNotFoundException if a serialized class cannot be loaded
124      */
125     @java.io.Serial
readObject(ObjectInputStream s)126     private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
127         ObjectInputStream.GetField fields = s.readFields();
128         Throwable exception = (Throwable) fields.get("exception", null);
129         if (exception != null) {
130             setCause(exception);
131         }
132     }
133 
134     /**
135      * To maintain compatibility with older implementation, write a serial
136      * "exception" field with the cause as the value.
137      *
138      * @param  out the {@code ObjectOutputStream} to which data is written
139      * @throws IOException if an I/O error occurs
140      */
141     @java.io.Serial
writeObject(ObjectOutputStream out)142     private void writeObject(ObjectOutputStream out) throws IOException {
143         ObjectOutputStream.PutField fields = out.putFields();
144         fields.put("exception", super.getCause());
145         out.writeFields();
146     }
147 
148 }
149