8210721: Replace legacy serial exception field with Throwable::cause

Reviewed-by: dfuchs, lancea
This commit is contained in:
Mandy Chung 2018-09-17 15:22:46 -07:00
parent b27f471bdd
commit b72ab42e49
9 changed files with 486 additions and 108 deletions

@ -25,6 +25,11 @@
package java.lang;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
/**
* Thrown when an application tries to load in a class through its
* string name using:
@ -56,15 +61,6 @@ public class ClassNotFoundException extends ReflectiveOperationException {
*/
private static final long serialVersionUID = 9176873029745254542L;
/**
* This field holds the exception ex if the
* ClassNotFoundException(String s, Throwable ex) constructor was
* used to instantiate the object
* @serial
* @since 1.2
*/
private Throwable ex;
/**
* Constructs a <code>ClassNotFoundException</code> with no detail message.
*/
@ -92,8 +88,7 @@ public class ClassNotFoundException extends ReflectiveOperationException {
* @since 1.2
*/
public ClassNotFoundException(String s, Throwable ex) {
super(s, null); // Disallow initCause
this.ex = ex;
super(s, ex); // Disallow initCause
}
/**
@ -108,18 +103,42 @@ public class ClassNotFoundException extends ReflectiveOperationException {
* @since 1.2
*/
public Throwable getException() {
return ex;
return super.getCause();
}
/**
* Returns the cause of this exception (the exception that was raised
* if an error occurred while attempting to load the class; otherwise
* {@code null}).
* Serializable fields for ClassNotFoundException.
*
* @return the cause of this exception.
* @since 1.4
* @serialField ex Throwable
*/
public Throwable getCause() {
return ex;
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("ex", Throwable.class)
};
/*
* Reconstitutes the ClassNotFoundException instance from a stream
* and initialize the cause properly when deserializing from an older
* version.
*
* The getException and getCause method returns the private "ex" field
* in the older implementation and ClassNotFoundException::cause
* was set to null.
*/
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
Throwable exception = (Throwable) fields.get("ex", null);
if (exception != null) {
setCause(exception);
}
}
/*
* To maintain compatibility with older implementation, write a serial
* "ex" field with the cause as the value.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
ObjectOutputStream.PutField fields = out.putFields();
fields.put("ex", super.getCause());
out.writeFields();
}
}

@ -25,6 +25,11 @@
package java.lang;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
/**
* Signals that an unexpected exception has occurred in a static initializer.
* An <code>ExceptionInInitializerError</code> is thrown to indicate that an
@ -47,16 +52,6 @@ public class ExceptionInInitializerError extends LinkageError {
*/
private static final long serialVersionUID = 1521711792217232256L;
/**
* This field holds the exception if the
* ExceptionInInitializerError(Throwable thrown) constructor was
* used to instantiate the object
*
* @serial
*
*/
private Throwable exception;
/**
* Constructs an <code>ExceptionInInitializerError</code> with
* <code>null</code> as its detail message string and with no saved
@ -64,7 +59,7 @@ public class ExceptionInInitializerError extends LinkageError {
* A detail message is a String that describes this particular exception.
*/
public ExceptionInInitializerError() {
initCause(null); // Disallow subsequent initCause
initCause(null); // Disallow subsequent initCause
}
/**
@ -76,23 +71,20 @@ public class ExceptionInInitializerError extends LinkageError {
* @param thrown The exception thrown
*/
public ExceptionInInitializerError(Throwable thrown) {
initCause(null); // Disallow subsequent initCause
this.exception = thrown;
super(null, thrown); // Disallow subsequent initCause
}
/**
* Constructs an ExceptionInInitializerError with the specified detail
* Constructs an {@code ExceptionInInitializerError} with the specified detail
* message string. A detail message is a String that describes this
* particular exception. The detail message string is saved for later
* retrieval by the {@link Throwable#getMessage()} method. There is no
* saved throwable object.
*
*
* @param s the detail message
*/
public ExceptionInInitializerError(String s) {
super(s);
initCause(null); // Disallow subsequent initCause
super(s, null); // Disallow subsequent initCause
}
/**
@ -109,18 +101,43 @@ public class ExceptionInInitializerError extends LinkageError {
* throwable object.
*/
public Throwable getException() {
return exception;
return super.getCause();
}
/**
* Returns the cause of this error (the exception that occurred
* during a static initialization that caused this error to be created).
* Serializable fields for ExceptionInInitializerError.
*
* @return the cause of this error or <code>null</code> if the
* cause is nonexistent or unknown.
* @since 1.4
* @serialField exception Throwable
*/
public Throwable getCause() {
return exception;
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("exception", Throwable.class)
};
/*
* Reconstitutes the ExceptionInInitializerError instance from a stream
* and initialize the cause properly when deserializing from an older
* version.
*
* The getException and getCause method returns the private "exception"
* field in the older implementation and ExceptionInInitializerError::cause
* was set to null.
*/
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
Throwable exception = (Throwable) fields.get("exception", null);
if (exception != null) {
setCause(exception);
}
}
/*
* To maintain compatibility with older implementation, write a serial
* "exception" field with the cause as the value.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
ObjectOutputStream.PutField fields = out.putFields();
fields.put("exception", super.getCause());
out.writeFields();
}
}

@ -2201,6 +2201,9 @@ public final class System {
return StringCoding.getBytesUTF8NoRepl(s);
}
public void setCause(Throwable t, Throwable cause) {
t.setCause(cause);
}
});
}
}

@ -466,6 +466,16 @@ public class Throwable implements Serializable {
return this;
}
/*
* This is called by readObject of a few exceptions such as
* ClassNotFoundException and ExceptionInInitializerError to deserialize
* a stream output from an older runtime version where the cause may
* have set to null.
*/
final void setCause(Throwable t) {
this.cause = t;
}
/**
* Returns a short description of this throwable.
* The result is the concatenation of:

@ -25,6 +25,12 @@
package java.lang.reflect;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import jdk.internal.misc.SharedSecrets;
/**
* InvocationTargetException is a checked exception that wraps
* an exception thrown by an invoked method or constructor.
@ -46,16 +52,6 @@ public class InvocationTargetException extends ReflectiveOperationException {
*/
private static final long serialVersionUID = 4085088731926701167L;
/**
* This field holds the target if the
* InvocationTargetException(Throwable target) constructor was
* used to instantiate the object
*
* @serial
*
*/
private Throwable target;
/**
* Constructs an {@code InvocationTargetException} with
* {@code null} as the target exception.
@ -70,8 +66,7 @@ public class InvocationTargetException extends ReflectiveOperationException {
* @param target the target exception
*/
public InvocationTargetException(Throwable target) {
super((Throwable)null); // Disallow initCause
this.target = target;
super(null, target); // Disallow initCause
}
/**
@ -82,8 +77,7 @@ public class InvocationTargetException extends ReflectiveOperationException {
* @param s the detail message
*/
public InvocationTargetException(Throwable target, String s) {
super(s, null); // Disallow initCause
this.target = target;
super(s, target); // Disallow initCause
}
/**
@ -96,17 +90,42 @@ public class InvocationTargetException extends ReflectiveOperationException {
* @return the thrown target exception (cause of this exception).
*/
public Throwable getTargetException() {
return target;
return super.getCause();
}
/**
* Returns the cause of this exception (the thrown target exception,
* which may be {@code null}).
* Serializable fields for UndeclaredThrowableException.
*
* @return the cause of this exception.
* @since 1.4
* @serialField target Throwable
*/
public Throwable getCause() {
return target;
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("target", Throwable.class)
};
/*
* Reconstitutes the InvocationTargetException instance from a stream
* and initialize the cause properly when deserializing from an older
* version.
*
* The getException and getCause method returns the private "target" field
* in the older implementation and InvocationTargetException::cause
* was set to null.
*/
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
Throwable exception = (Throwable) fields.get("target", null);
if (exception != null) {
SharedSecrets.getJavaLangAccess().setCause(this, exception);
}
}
/*
* To maintain compatibility with older implementation, write a serial
* "target" field with the cause as the value.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
ObjectOutputStream.PutField fields = out.putFields();
fields.put("target", super.getCause());
out.writeFields();
}
}

@ -25,6 +25,12 @@
package java.lang.reflect;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import jdk.internal.misc.SharedSecrets;
/**
* Thrown by a method invocation on a proxy instance if its invocation
* handler's {@link InvocationHandler#invoke invoke} method throws a
@ -58,12 +64,6 @@ package java.lang.reflect;
public class UndeclaredThrowableException extends RuntimeException {
static final long serialVersionUID = 330127114055056639L;
/**
* the undeclared checked exception that was thrown
* @serial
*/
private Throwable undeclaredThrowable;
/**
* Constructs an {@code UndeclaredThrowableException} with the
* specified {@code Throwable}.
@ -72,8 +72,7 @@ public class UndeclaredThrowableException extends RuntimeException {
* that was thrown
*/
public UndeclaredThrowableException(Throwable undeclaredThrowable) {
super((Throwable) null); // Disallow initCause
this.undeclaredThrowable = undeclaredThrowable;
super(null, undeclaredThrowable); // Disallow initCause
}
/**
@ -87,8 +86,7 @@ public class UndeclaredThrowableException extends RuntimeException {
public UndeclaredThrowableException(Throwable undeclaredThrowable,
String s)
{
super(s, null); // Disallow initCause
this.undeclaredThrowable = undeclaredThrowable;
super(s, undeclaredThrowable); // Disallow initCause
}
/**
@ -102,18 +100,38 @@ public class UndeclaredThrowableException extends RuntimeException {
* @return the undeclared checked exception that was thrown
*/
public Throwable getUndeclaredThrowable() {
return undeclaredThrowable;
return super.getCause();
}
/**
* Returns the cause of this exception (the {@code Throwable}
* instance wrapped in this {@code UndeclaredThrowableException},
* which may be {@code null}).
* Serializable fields for UndeclaredThrowableException.
*
* @return the cause of this exception.
* @since 1.4
* @serialField undeclaredThrowable Throwable
*/
public Throwable getCause() {
return undeclaredThrowable;
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("undeclaredThrowable", Throwable.class)
};
/*
* Reconstitutes the UndeclaredThrowableException instance from a stream
* and initialize the cause properly when deserializing from an older
* version.
*/
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
Throwable exception = (Throwable) fields.get("undeclaredThrowable", null);
if (exception != null) {
SharedSecrets.getJavaLangAccess().setCause(this, exception);
}
}
/*
* To maintain compatibility with older implementation, write a serial
* "ex" field with the cause as the value.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
ObjectOutputStream.PutField fields = out.putFields();
fields.put("undeclaredThrowable", super.getCause());
out.writeFields();
}
}

@ -25,6 +25,12 @@
package java.security;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import jdk.internal.misc.SharedSecrets;
/**
* This exception is thrown by
* {@code doPrivileged(PrivilegedExceptionAction)} and
@ -52,11 +58,6 @@ public class PrivilegedActionException extends Exception {
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = 4724086851538908602L;
/**
* @serial
*/
private Exception exception;
/**
* Constructs a new PrivilegedActionException &quot;wrapping&quot;
* the specific Exception.
@ -64,8 +65,7 @@ public class PrivilegedActionException extends Exception {
* @param exception The exception thrown
*/
public PrivilegedActionException(Exception exception) {
super((Throwable)null); // Disallow initCause
this.exception = exception;
super(null, exception); // Disallow initCause
}
/**
@ -84,23 +84,49 @@ public class PrivilegedActionException extends Exception {
* AccessControlContext)
*/
public Exception getException() {
return exception;
}
/**
* Returns the cause of this exception (the exception thrown by
* the privileged computation that resulted in this
* {@code PrivilegedActionException}).
*
* @return the cause of this exception.
* @since 1.4
*/
public Throwable getCause() {
return exception;
return (Exception)super.getCause();
}
public String toString() {
String s = getClass().getName();
return (exception != null) ? (s + ": " + exception.toString()) : s;
Throwable cause = super.getCause();
return (cause != null) ? (s + ": " + cause.toString()) : s;
}
/**
* Serializable fields for UndeclaredThrowableException.
*
* @serialField undeclaredThrowable Throwable
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("exception", Exception.class)
};
/*
* Reconstitutes the PrivilegedActionException instance from a stream
* and initialize the cause properly when deserializing from an older
* version.
*
* The getException and getCause method returns the private "exception"
* field in the older implementation and PrivilegedActionException::cause
* was set to null.
*/
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
Exception exception = (Exception) fields.get("exception", null);
if (exception != null) {
SharedSecrets.getJavaLangAccess().setCause(this, exception);
}
}
/*
* To maintain compatibility with older implementation, write a serial
* "exception" field with the cause as the value.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
ObjectOutputStream.PutField fields = out.putFields();
fields.put("exception", super.getCause());
out.writeFields();
}
}

@ -305,4 +305,10 @@ public interface JavaLangAccess {
* @throws IllegalArgumentException for malformed surrogates
*/
byte[] getBytesUTF8NoRepl(String s);
/**
* Set the cause of Throwable
* @param cause set t's cause to new value
*/
void setCause(Throwable t, Throwable cause);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,10 +22,15 @@
*/
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.PrivilegedActionException;
import java.util.Base64;
import java.util.Map;
/**
* @test
* @bug 4385429 8004928
* @bug 4385429 8004928 8210721
* @summary Certain legacy chained exceptions throw IllegalArgumentException
* upon deserialization if "causative exception" is null.
* @author Josh Bloch
@ -33,18 +38,31 @@ import java.io.*;
public class LegacyChainedExceptionSerialization {
private static Throwable[] broken = {
new ClassNotFoundException(),
new ClassNotFoundException("bar", new IOException("reading class file")),
new ExceptionInInitializerError(),
new ExceptionInInitializerError(new NullPointerException("foo")),
new java.lang.reflect.UndeclaredThrowableException(null),
new java.lang.reflect.UndeclaredThrowableException(new IllegalArgumentException("foo")),
new java.lang.reflect.InvocationTargetException(null),
new java.security.PrivilegedActionException(null)
new java.lang.reflect.InvocationTargetException(new Error("goo")),
new java.security.PrivilegedActionException(null),
new java.security.PrivilegedActionException(new IOException("foo")),
};
public static void main(String[] args) throws Exception {
for (int i=0; i<broken.length; i++)
test(broken[i]);
for (Map.Entry<String, Throwable> e : SERIALIZED_DATA.entrySet()) {
Throwable t = deserialize(e.getKey());
verify(t, e.getValue());
}
testOverriddenGetCause();
}
private static void test(Throwable e) throws Exception {
private static Throwable test(Throwable e) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bout);
out.writeObject(e);
@ -54,5 +72,247 @@ public class LegacyChainedExceptionSerialization {
new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bin);
Throwable clone = (Throwable) in.readObject();
return clone;
}
private static void testOverriddenGetCause() throws Exception {
SubClass sc = new SubClass(new NullPointerException());
SubClass clone = (SubClass)test(sc);
Throwable cause = clone.getException();
if (!(cause instanceof NullPointerException) || cause.getMessage() != null) {
throw new RuntimeException("unexpected cause: " + cause);
}
}
private static Throwable deserialize(String ser) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
try (ByteArrayInputStream bin = new ByteArrayInputStream(decoder.decode(ser));
ObjectInputStream ois = new ObjectInputStream(bin)) {
return (Throwable)ois.readObject();
}
}
/*
* Verify the deserialization of the serialized data from an old version.
* See SERIALIZED_DATA.
*/
private static void verify(Throwable t, Throwable expected) {
String msg = expected.getMessage();
Throwable cause = expected.getCause();
if (t.getMessage() != msg && msg != null && !msg.equals(t.getMessage())) {
throw new RuntimeException("unexpected message: " + t.getMessage()
+ " expected: " + msg);
}
Throwable e = t.getCause();
if (e.getClass() != cause.getClass()) {
throw new RuntimeException("unexpected cause: " + t.getCause());
}
String causedBy = cause.getMessage();
if (e.getMessage() != causedBy) {
if (e.getMessage() == null || causedBy == null || !causedBy.equals(e.getMessage())) {
throw new RuntimeException("unexpected message: " + t.getMessage()
+ " expected: " + causedBy);
}
}
Throwable exception = null;
if (t instanceof ExceptionInInitializerError) {
exception = ((ExceptionInInitializerError)t).getException();
} else if (t instanceof ClassNotFoundException) {
exception = ((ClassNotFoundException)t).getException();
} else if (t instanceof InvocationTargetException) {
exception = ((InvocationTargetException) t).getTargetException();
} else if (t instanceof UndeclaredThrowableException) {
exception = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
} else if (t instanceof PrivilegedActionException) {
exception = ((PrivilegedActionException) t).getException();
} else {
// skip the cause == exception check below
e = null;
}
if (e != exception) {
throw new RuntimeException("unexpected exception: " + exception);
}
}
static class SubClass extends ExceptionInInitializerError {
public SubClass(Throwable t) {
super(t);
}
@Override
public Throwable getCause() {
return new Throwable("always new");
}
}
/*
* The following strings are base64-encoded serialized data generated
* by running the jdk10SerializeThrowable method with JDK 10 runtime.
*
* private static void jdk10SerializeThrowable(Throwable e) throws Exception {
* Base64.Encoder encoder = Base64.getEncoder();
* try (ByteArrayOutputStream os = new ByteArrayOutputStream();
* ObjectOutputStream out = new ObjectOutputStream(os)) {
* out.writeObject(e);
* out.flush();
* String s = encoder.encodeToString(os.toByteArray());
* for (int i=0; i < s.length();) {
* int end = Math.min(i+60, s.length());
* CharSequence seq = s.subSequence(i, end);
* System.out.format("\"%s\" +%n", seq);
* i = end;
* }
* }
* }
*/
private static final String EIIE_OLD_VERSION =
"rO0ABXNyACVqYXZhLmxhbmcuRXhjZXB0aW9uSW5Jbml0aWFsaXplckVycm9y" +
"FR400Amhk4ACAAFMAAlleGNlcHRpb250ABVMamF2YS9sYW5nL1Rocm93YWJs" +
"ZTt4cgAWamF2YS5sYW5nLkxpbmthZ2VFcnJvcjGtS1U0qEq6AgAAeHIAD2ph" +
"dmEubGFuZy5FcnJvckUdNlaLgg5WAgAAeHIAE2phdmEubGFuZy5UaHJvd2Fi" +
"bGXVxjUnOXe4ywMABEwABWNhdXNlcQB+AAFMAA1kZXRhaWxNZXNzYWdldAAS" +
"TGphdmEvbGFuZy9TdHJpbmc7WwAKc3RhY2tUcmFjZXQAHltMamF2YS9sYW5n" +
"L1N0YWNrVHJhY2VFbGVtZW50O0wAFHN1cHByZXNzZWRFeGNlcHRpb25zdAAQ" +
"TGphdmEvdXRpbC9MaXN0O3hwcHB1cgAeW0xqYXZhLmxhbmcuU3RhY2tUcmFj" +
"ZUVsZW1lbnQ7AkYqPDz9IjkCAAB4cAAAAAFzcgAbamF2YS5sYW5nLlN0YWNr" +
"VHJhY2VFbGVtZW50YQnFmiY23YUCAAhCAAZmb3JtYXRJAApsaW5lTnVtYmVy" +
"TAAPY2xhc3NMb2FkZXJOYW1lcQB+AAVMAA5kZWNsYXJpbmdDbGFzc3EAfgAF" +
"TAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABUwACm1vZHVsZU5h" +
"bWVxAH4ABUwADW1vZHVsZVZlcnNpb25xAH4ABXhwAQAAAAd0AANhcHB0AARU" +
"ZXN0dAAJVGVzdC5qYXZhdAAEbWFpbnBwc3IAH2phdmEudXRpbC5Db2xsZWN0" +
"aW9ucyRFbXB0eUxpc3R6uBe0PKee3gIAAHhweHNyAB5qYXZhLmxhbmcuTnVs" +
"bFBvaW50ZXJFeGNlcHRpb25HpaGO/zHhuAIAAHhyABpqYXZhLmxhbmcuUnVu" +
"dGltZUV4Y2VwdGlvbp5fBkcKNIPlAgAAeHIAE2phdmEubGFuZy5FeGNlcHRp" +
"b27Q/R8+GjscxAIAAHhxAH4ABHEAfgAWdAADZm9vdXEAfgAJAAAAAXNxAH4A" +
"CwEAAAAHcQB+AA1xAH4ADnEAfgAPcQB+ABBwcHEAfgASeA==";
private static final String CNFE_OLD_VERSION =
"rO0ABXNyACBqYXZhLmxhbmcuQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbn9azWY+" +
"1CCOAgABTAACZXh0ABVMamF2YS9sYW5nL1Rocm93YWJsZTt4cgAmamF2YS5s" +
"YW5nLlJlZmxlY3RpdmVPcGVyYXRpb25FeGNlcHRpb24AAAAAB1vNFQIAAHhy" +
"ABNqYXZhLmxhbmcuRXhjZXB0aW9u0P0fPho7HMQCAAB4cgATamF2YS5sYW5n" +
"LlRocm93YWJsZdXGNSc5d7jLAwAETAAFY2F1c2VxAH4AAUwADWRldGFpbE1l" +
"c3NhZ2V0ABJMamF2YS9sYW5nL1N0cmluZztbAApzdGFja1RyYWNldAAeW0xq" +
"YXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAUc3VwcHJlc3NlZEV4Y2Vw" +
"dGlvbnN0ABBMamF2YS91dGlsL0xpc3Q7eHBwdAADYmFydXIAHltMamF2YS5s" +
"YW5nLlN0YWNrVHJhY2VFbGVtZW50OwJGKjw8/SI5AgAAeHAAAAABc3IAG2ph" +
"dmEubGFuZy5TdGFja1RyYWNlRWxlbWVudGEJxZomNt2FAgAIQgAGZm9ybWF0" +
"SQAKbGluZU51bWJlckwAD2NsYXNzTG9hZGVyTmFtZXEAfgAFTAAOZGVjbGFy" +
"aW5nQ2xhc3NxAH4ABUwACGZpbGVOYW1lcQB+AAVMAAptZXRob2ROYW1lcQB+" +
"AAVMAAptb2R1bGVOYW1lcQB+AAVMAA1tb2R1bGVWZXJzaW9ucQB+AAV4cAEA" +
"AAAMdAADYXBwdAAEVGVzdHQACVRlc3QuamF2YXQABG1haW5wcHNyAB9qYXZh" +
"LnV0aWwuQ29sbGVjdGlvbnMkRW1wdHlMaXN0ergXtDynnt4CAAB4cHhzcgAT" +
"amF2YS5pby5JT0V4Y2VwdGlvbmyAc2RlJfCrAgAAeHEAfgADcQB+ABV0ABJy" +
"ZWFkaW5nIGNsYXNzIGZpbGV1cQB+AAoAAAABc3EAfgAMAQAAAAxxAH4ADnEA" +
"fgAPcQB+ABBxAH4AEXBwcQB+ABN4";
private static final String ITE1_OLD_VERSION =
"rO0ABXNyACtqYXZhLmxhbmcucmVmbGVjdC5JbnZvY2F0aW9uVGFyZ2V0RXhj" +
"ZXB0aW9uOLEmjtZxJG8CAAFMAAZ0YXJnZXR0ABVMamF2YS9sYW5nL1Rocm93" +
"YWJsZTt4cgAmamF2YS5sYW5nLlJlZmxlY3RpdmVPcGVyYXRpb25FeGNlcHRp" +
"b24AAAAAB1vNFQIAAHhyABNqYXZhLmxhbmcuRXhjZXB0aW9u0P0fPho7HMQC" +
"AAB4cgATamF2YS5sYW5nLlRocm93YWJsZdXGNSc5d7jLAwAETAAFY2F1c2Vx" +
"AH4AAUwADWRldGFpbE1lc3NhZ2V0ABJMamF2YS9sYW5nL1N0cmluZztbAApz" +
"dGFja1RyYWNldAAeW0xqYXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAU" +
"c3VwcHJlc3NlZEV4Y2VwdGlvbnN0ABBMamF2YS91dGlsL0xpc3Q7eHBwdAAD" +
"YmFydXIAHltMamF2YS5sYW5nLlN0YWNrVHJhY2VFbGVtZW50OwJGKjw8/SI5" +
"AgAAeHAAAAABc3IAG2phdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudGEJxZom" +
"Nt2FAgAIQgAGZm9ybWF0SQAKbGluZU51bWJlckwAD2NsYXNzTG9hZGVyTmFt" +
"ZXEAfgAFTAAOZGVjbGFyaW5nQ2xhc3NxAH4ABUwACGZpbGVOYW1lcQB+AAVM" +
"AAptZXRob2ROYW1lcQB+AAVMAAptb2R1bGVOYW1lcQB+AAVMAA1tb2R1bGVW" +
"ZXJzaW9ucQB+AAV4cAEAAAARdAADYXBwdAAEVGVzdHQACVRlc3QuamF2YXQA" +
"BG1haW5wcHNyAB9qYXZhLnV0aWwuQ29sbGVjdGlvbnMkRW1wdHlMaXN0ergX" +
"tDynnt4CAAB4cHhzcgAPamF2YS5sYW5nLkVycm9yRR02VouCDlYCAAB4cQB+" +
"AARxAH4AFXQAA2Zvb3VxAH4ACgAAAAFzcQB+AAwBAAAAEXEAfgAOcQB+AA9x" +
"AH4AEHEAfgARcHBxAH4AE3g=";
private static final String ITE2_OLD_VERSION =
"rO0ABXNyACtqYXZhLmxhbmcucmVmbGVjdC5JbnZvY2F0aW9uVGFyZ2V0RXhj" +
"ZXB0aW9uOLEmjtZxJG8CAAFMAAZ0YXJnZXR0ABVMamF2YS9sYW5nL1Rocm93" +
"YWJsZTt4cgAmamF2YS5sYW5nLlJlZmxlY3RpdmVPcGVyYXRpb25FeGNlcHRp" +
"b24AAAAAB1vNFQIAAHhyABNqYXZhLmxhbmcuRXhjZXB0aW9u0P0fPho7HMQC" +
"AAB4cgATamF2YS5sYW5nLlRocm93YWJsZdXGNSc5d7jLAwAETAAFY2F1c2Vx" +
"AH4AAUwADWRldGFpbE1lc3NhZ2V0ABJMamF2YS9sYW5nL1N0cmluZztbAApz" +
"dGFja1RyYWNldAAeW0xqYXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAU" +
"c3VwcHJlc3NlZEV4Y2VwdGlvbnN0ABBMamF2YS91dGlsL0xpc3Q7eHBwcHVy" +
"AB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhw" +
"AAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIA" +
"CEIABmZvcm1hdEkACmxpbmVOdW1iZXJMAA9jbGFzc0xvYWRlck5hbWVxAH4A" +
"BUwADmRlY2xhcmluZ0NsYXNzcQB+AAVMAAhmaWxlTmFtZXEAfgAFTAAKbWV0" +
"aG9kTmFtZXEAfgAFTAAKbW9kdWxlTmFtZXEAfgAFTAANbW9kdWxlVmVyc2lv" +
"bnEAfgAFeHABAAAAEnQAA2FwcHQABFRlc3R0AAlUZXN0LmphdmF0AARtYWlu" +
"cHBzcgAfamF2YS51dGlsLkNvbGxlY3Rpb25zJEVtcHR5TGlzdHq4F7Q8p57e" +
"AgAAeHB4c3IAD2phdmEubGFuZy5FcnJvckUdNlaLgg5WAgAAeHEAfgAEcQB+" +
"ABR0AANnb291cQB+AAkAAAABc3EAfgALAQAAABJxAH4ADXEAfgAOcQB+AA9x" +
"AH4AEHBwcQB+ABJ4";
private static final String UTE1_OLD_VERSION =
"rO0ABXNyAC5qYXZhLmxhbmcucmVmbGVjdC5VbmRlY2xhcmVkVGhyb3dhYmxl" +
"RXhjZXB0aW9uBJTY3HP5/P8CAAFMABN1bmRlY2xhcmVkVGhyb3dhYmxldAAV" +
"TGphdmEvbGFuZy9UaHJvd2FibGU7eHIAGmphdmEubGFuZy5SdW50aW1lRXhj" +
"ZXB0aW9unl8GRwo0g+UCAAB4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4a" +
"OxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNh" +
"dXNlcQB+AAFMAA1kZXRhaWxNZXNzYWdldAASTGphdmEvbGFuZy9TdHJpbmc7" +
"WwAKc3RhY2tUcmFjZXQAHltMamF2YS9sYW5nL1N0YWNrVHJhY2VFbGVtZW50" +
"O0wAFHN1cHByZXNzZWRFeGNlcHRpb25zdAAQTGphdmEvdXRpbC9MaXN0O3hw" +
"cHQAA2JhcnVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8" +
"PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRh" +
"CcWaJjbdhQIACEIABmZvcm1hdEkACmxpbmVOdW1iZXJMAA9jbGFzc0xvYWRl" +
"ck5hbWVxAH4ABUwADmRlY2xhcmluZ0NsYXNzcQB+AAVMAAhmaWxlTmFtZXEA" +
"fgAFTAAKbWV0aG9kTmFtZXEAfgAFTAAKbW9kdWxlTmFtZXEAfgAFTAANbW9k" +
"dWxlVmVyc2lvbnEAfgAFeHABAAAAE3QAA2FwcHQABFRlc3R0AAlUZXN0Lmph" +
"dmF0AARtYWlucHBzcgAfamF2YS51dGlsLkNvbGxlY3Rpb25zJEVtcHR5TGlz" +
"dHq4F7Q8p57eAgAAeHB4c3IAImphdmEubGFuZy5JbGxlZ2FsQXJndW1lbnRF" +
"eGNlcHRpb261iXPTfWaPvAIAAHhxAH4AAnEAfgAVdAADZm9vdXEAfgAKAAAA" +
"AXNxAH4ADAEAAAATcQB+AA5xAH4AD3EAfgAQcQB+ABFwcHEAfgATeA==";
private static final String UTE2_OLD_VERSION =
"rO0ABXNyAC5qYXZhLmxhbmcucmVmbGVjdC5VbmRlY2xhcmVkVGhyb3dhYmxl" +
"RXhjZXB0aW9uBJTY3HP5/P8CAAFMABN1bmRlY2xhcmVkVGhyb3dhYmxldAAV" +
"TGphdmEvbGFuZy9UaHJvd2FibGU7eHIAGmphdmEubGFuZy5SdW50aW1lRXhj" +
"ZXB0aW9unl8GRwo0g+UCAAB4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4a" +
"OxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNh" +
"dXNlcQB+AAFMAA1kZXRhaWxNZXNzYWdldAASTGphdmEvbGFuZy9TdHJpbmc7" +
"WwAKc3RhY2tUcmFjZXQAHltMamF2YS9sYW5nL1N0YWNrVHJhY2VFbGVtZW50" +
"O0wAFHN1cHByZXNzZWRFeGNlcHRpb25zdAAQTGphdmEvdXRpbC9MaXN0O3hw" +
"cHB1cgAeW0xqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnQ7AkYqPDz9IjkC" +
"AAB4cAAAAAFzcgAbamF2YS5sYW5nLlN0YWNrVHJhY2VFbGVtZW50YQnFmiY2" +
"3YUCAAhCAAZmb3JtYXRJAApsaW5lTnVtYmVyTAAPY2xhc3NMb2FkZXJOYW1l" +
"cQB+AAVMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwA" +
"Cm1ldGhvZE5hbWVxAH4ABUwACm1vZHVsZU5hbWVxAH4ABUwADW1vZHVsZVZl" +
"cnNpb25xAH4ABXhwAQAAABR0AANhcHB0AARUZXN0dAAJVGVzdC5qYXZhdAAE" +
"bWFpbnBwc3IAH2phdmEudXRpbC5Db2xsZWN0aW9ucyRFbXB0eUxpc3R6uBe0" +
"PKee3gIAAHhweHNyACJqYXZhLmxhbmcuSWxsZWdhbEFyZ3VtZW50RXhjZXB0" +
"aW9utYlz031mj7wCAAB4cQB+AAJxAH4AFHQAA2dvb3VxAH4ACQAAAAFzcQB+" +
"AAsBAAAAFHEAfgANcQB+AA5xAH4AD3EAfgAQcHBxAH4AEng=";
private static final String PAE_OLD_VERSION =
"rO0ABXNyACdqYXZhLnNlY3VyaXR5LlByaXZpbGVnZWRBY3Rpb25FeGNlcHRp" +
"b25Bj1P2UhH1ugIAAUwACWV4Y2VwdGlvbnQAFUxqYXZhL2xhbmcvRXhjZXB0" +
"aW9uO3hyABNqYXZhLmxhbmcuRXhjZXB0aW9u0P0fPho7HMQCAAB4cgATamF2" +
"YS5sYW5nLlRocm93YWJsZdXGNSc5d7jLAwAETAAFY2F1c2V0ABVMamF2YS9s" +
"YW5nL1Rocm93YWJsZTtMAA1kZXRhaWxNZXNzYWdldAASTGphdmEvbGFuZy9T" +
"dHJpbmc7WwAKc3RhY2tUcmFjZXQAHltMamF2YS9sYW5nL1N0YWNrVHJhY2VF" +
"bGVtZW50O0wAFHN1cHByZXNzZWRFeGNlcHRpb25zdAAQTGphdmEvdXRpbC9M" +
"aXN0O3hwcHB1cgAeW0xqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnQ7AkYq" +
"PDz9IjkCAAB4cAAAAAFzcgAbamF2YS5sYW5nLlN0YWNrVHJhY2VFbGVtZW50" +
"YQnFmiY23YUCAAhCAAZmb3JtYXRJAApsaW5lTnVtYmVyTAAPY2xhc3NMb2Fk" +
"ZXJOYW1lcQB+AAVMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVx" +
"AH4ABUwACm1ldGhvZE5hbWVxAH4ABUwACm1vZHVsZU5hbWVxAH4ABUwADW1v" +
"ZHVsZVZlcnNpb25xAH4ABXhwAQAAABd0AANhcHB0AARUZXN0dAAJVGVzdC5q" +
"YXZhdAAEbWFpbnBwc3IAH2phdmEudXRpbC5Db2xsZWN0aW9ucyRFbXB0eUxp" +
"c3R6uBe0PKee3gIAAHhweHNyABNqYXZhLmlvLklPRXhjZXB0aW9ubIBzZGUl" +
"8KsCAAB4cQB+AAJxAH4AFHQAA2Zvb3VxAH4ACQAAAAFzcQB+AAsBAAAAF3EA" +
"fgANcQB+AA5xAH4AD3EAfgAQcHBxAH4AEng=";
private static Map<String, Throwable> SERIALIZED_DATA = Map.of(
EIIE_OLD_VERSION, new ExceptionInInitializerError(new NullPointerException("foo")),
CNFE_OLD_VERSION, new ClassNotFoundException("bar", new IOException("reading class file")),
ITE1_OLD_VERSION, new InvocationTargetException(new Error("foo"), "bar"),
ITE2_OLD_VERSION, new InvocationTargetException(new Error("goo")),
UTE1_OLD_VERSION, new UndeclaredThrowableException(new IllegalArgumentException("foo"), "bar"),
UTE2_OLD_VERSION, new UndeclaredThrowableException(new IllegalArgumentException("goo")),
PAE_OLD_VERSION, new PrivilegedActionException(new IOException("foo"))
);
}