RFR JDK-8209553: ExceptionInInitializerError can have a default detail message if the cause is given
Peter Levart
peter.levart at gmail.com
Fri Aug 17 07:24:58 UTC 2018
On 08/17/2018 01:54 AM, mandy chung wrote:
>
>
> On 8/16/18 4:48 PM, joe darcy wrote:
>>>> Just a question. Why does "private Throwable exception" field in
>>>> ExceptionInInitializerError exist? Was it there before there was a
>>>> "cause" in Throwable and later still remained there because of
>>>> serialization format? Would it be possible to "simulate" its effect
>>>> for serialization using "serialPersistentFields" and
>>>> ObjectOutputStream.PutField?
>>>
>>> Thanks for asking. I meant to mention this and it'd be nice to
>>> follow up this in a separate issue.
>>>
>>> The private exception field exists since 1.1 and kept there for
>>> serialization. getException in existing releases returns the
>>> exception field. I can't think of any way to remove the exception
>>> field in JDK n to deserialize it with older JDK x unless JDK x was
>>> changed to write the exception field with the cause or getException
>>> to return cause.
>>
>> Just a quick comment, it is possible, although a bit tedious, to
>> remove a field and retain serial compatibility if
>> readObject/writeObject methods are added to the new version of the
>> class. There are a few examples of doing this kind of conversion in
>> the JDK, such as for BigInteger.
>
>
> Thanks Joe. In EIIE case, ideally we should remove the private
> exception field and then write that to the serialize stream.
> However, PutField::put requires the field to be present in
> the current class; otherwise it throws IAE.
>
> ObjectOutputStream.PutField fields = s.putFields();
> fields.put("exception", getCause());
Not necessarily. Check ConcurrentHashMap for example. It contains
several "pseudo" fields, declared with the "serialPersistentFields"
static final field.
The only problem with this approach is that while deserializing the
Throwable part of the ExceptionInInitializerError from the serial stream
produced by an old version of EIIE, the cause field will already be
deserialized as null and later in ExceptionInInitializerError.readObject
when "exception" pseudo field is read-in, its value would have to be
written over Throwable.cause field, but public API will not allow that
(re-initialization of cause is not permitted), so some package-private
API would have to be used to overwrite "cause".
But this same problem is present even if you keep the physical
"exception" field in the ExceptionInInitializerError. You have to be
prepared to deserialize an old version of EIIE where the "cause" is null
and the "exception" is non-null.
Regards, Peter
>
> I haven't digged the history but I assume a field in BigInteger
> was not renamed/removed.
>
> Any other suggestion would be appreciated.
>
> Mandy
More information about the core-libs-dev
mailing list