RFR: jsr166 jdk9 integration wave 2

Peter Levart peter.levart at gmail.com
Thu Dec 3 09:22:02 UTC 2015


Hi Martin,

On 12/03/2015 01:51 AM, Martin Buchholz wrote:
> We're stuck.  Peter wants to make Throwables cloneable, I want to
> reverse the order of throwables and add the past Throwable as a
> suppressed exception to the exception of a dependent action, and Doug
> wants the current webrev behavior of adding the dependent action as a
> suppressed exception of the source.
>
> I'm willing to accept the small incompatibility of throwing a
> different exception when everything fails; the existing spec doesn't
> promise what happens in this case.

As said in the other thread, I don't want to delay the changes to 
CompletableFuture with the support for cloning of exception. If this 
ever gets accepted (and probably won't) the CompletableFuture and 
ForkJoinTask could be revisited.

I see we have 3 options now for CompletableFuture:

- do nothing (ignore whenComplete exception when previous stage 
completes exceptionally too)
- add whenComplete exception to the exception from previous stage (as 
proposed currently in wave 2) which is thread-safe, but modifies the 
exceptional outcome of previous stage after it has already completed and 
thus could non-deterministically change the behavior of existing code 
(very unlikely, but possible).
- add the exception from previous stage to whenComplete exception (as 
endorsed by Martin) which changes the behavior and bends the spec. a little

What about the 4th option (keep current behavior, but try the 
best-effort with reflection to make new exception of the same type):

...
             } catch (Throwable ex) {
                 if (x == null) {
                     x = ex;
                 } else {
                     // try to create new exception with same:
                     // type, cause, suppressed exceptions and 
stack-trace...
                     Throwable nx;
                     Class<?> xClass = x.getClass();
                     try {
                         Constructor<?> xConstr = 
xClass.getConstructor(Throwable.class);
                         nx = (Throwable) xConstr.newInstance(x.getCause());
                     } catch (Exception e1) {
                         try {
                             nx = (Throwable) xClass.newInstance();
                             nx.initCause(x.getCause());
                         } catch (Exception e2) {
                             // no luck
                             nx = null;
                         }
                     }
                     if (nx != null) {
                         // inherit stack-trace of original exception
                         nx.setStackTrace(x.getStackTrace());
                         // inherit suppressed exceptions
                         for (Throwable sx : x.getSuppressed()) {
                             nx.addSuppressed(sx);
                         }
                         // add 'ex' as a final suppressed exception
                         nx.addSuppressed(ex);
                         x = nx;
                     }
                 }
             }
             completeThrowable(x, r);

...



Note that such code and similar code in 
ForkJoinTask.getThrowableException will probably have to be modified for 
jigsaw to include dynamic addition of read-edge to the module of 
exception class...

Regards, Peter




More information about the core-libs-dev mailing list