Updated ARM Spec
joe.darcy at oracle.com
Mon Aug 23 12:45:19 PDT 2010
Rémi Forax wrote:
> Le 23/08/2010 12:29, David Holmes a écrit :
>> Rémi Forax said the following on 08/23/10 20:23:
>>> Le 23/08/2010 12:09, David Holmes a écrit :
>>>> Rémi Forax said the following on 08/23/10 20:06:
>>>>> You can explicitly call setStackTrace() on a shared immutable
>>>>> exception, hence there is a problem.
>>>>> addSupressedExceptions() will have the same issue.
>>>> I stand corrected. The Java side of the code couldn't care less
>>>> about the VM level backtrace - it just installs a Java array. :(
>>>>> I think the fix is to:
>>>>> - silently discard the stack trace taken as argument of
>>>>> setStackTrace() if the cause is 'null' (or not 'this')
>>>>> - silently don't register suppressed-exceptions if cause is 'null'
>>>> I think the Java code should be able to recognize a Throwable
>>>> instance that should not allow these things to be set, and simply
>>>> ignore the request. However that is a change in the spec for
>>> Yes, setStackTrace() can 'not succeed'.
>>> And the way to recognize such Throwable instance is to check is the
>>> field 'cause' is null.
>> Except if someone invokes setCause(null).
> setCause(null) should set the field cause to this.
> For Throwable(null) and Throwable(message, null), null should also be
> The other solution is to use the field suppressedExceptions with the
> invariant that if
> it's null, it's an immutable shared exception.
>> By the way, probing further, the non-OOME shared pre-allocated
>> instances do not guard themselves against fillInStackTrace being
>> invoked upon them. That is arguably an additional bug. I say arguably
>> simply because in the circumstances under which those other exceptions
>> are thrown, having a misleading stacktrace is probably the least of
>> the application's worries.
> yes, you right.
To recap, Throwable objects have several pieces of mutable state:
* the cause; this is a write-at-most-once value that can be set set via
a constructor, like Throwable(Throwable cause) or Throwable(String
message, Throwable cause), or set after construction via the
Throwable.initCause method. (Setting the cause to null prevents future
* the stack trace; set by fillInStackTrace() or
setStackTrace(StackTraceElement stackTrace) -- there doesn't seem to
be any API prohibition against setting the stack trace multiple times
* suppressed exceptions : new functionality added to support
try-with-resources statements/ARM blocks. Modified via calling
Focusing just on suppressed exceptions, to support the JVM reusing
exception objects, the Throwable API should have some idiom to indicate
suppressed exception information should *not* be recorded. Logically
this amount to having the list of exceptions be a zero-length list which
just discards adds.
I'm hesitant to overload a null cause with discarding suppressed
exceptions too. Instead, I propose the following:
* a null value of the suppressedException field indicates
addSuppressedException is a no-op.
* the suppressedException field is initialized to point to a sentinel
list in Throwable, something non-null that can be used for == checks.
With this protocol, the "raw" Throwable objects created by the JVM get
the addSuppressedException is a no-op behavior for free.
* if the first call to addSuppressedException has this as an argument,
the suppressedException field is null-ed; otherwise, a list is appended
to as usual.
More information about the hotspot-runtime-dev