Hi Peter, I've done this trick before to perform Throwable cloning. You have to hunt for the constructors in this order: 1. Walk the type of the cause and super types by calling getConstructor(String, type of cause). (java.io.WriteAbortedException and javax.mail.MessagingException) 2. Walk the type of the cause and super types by calling getConstructor(type of cause, String) (I've seen this but, I can't seem to find an example) 3. getConstructor(String) + initCause (java.io.InvalidObjectException) 4. Walk the type of the cause and super types by calling getConstructor(type of cause). (java.awt.print.PrinterIOException) 5. getConstructor() + initCause. (java.nio.BufferOverflowException) 6. Look at the return type of methods declared in the cause type and assume there is a constructor matching the type or no repeating types. (java.nio.charset.MalformedInputException, java.lang.EnumConstantNotPresentException, java.util.regex.PatternSyntaxException)
In the end all of that can still fail. Exceptions can be private subclasses of public classes so that gets interesting with reflection too. Jason =========== 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