Here is a slightly improved version:
private static final StackTraceElementProxy[] NO_STACK_TRACE=new StackTraceElementProxy[0]; public ThrowableProxy(Throwable throwable) { this(throwable, null, false); } public ThrowableProxy(Throwable throwable, Set<Throwable> exclude, boolean circular) { this.throwable = throwable; this.message = throwable.getMessage(); if (!circular) { this.className = throwable.getClass().getName(); this.stackTraceElementProxyArray = ThrowableProxyUtil.steArrayToStepArray(throwable .getStackTrace()); Throwable nested = throwable.getCause(); if (nested != null) { if (exclude==null) { exclude = createExcludeSet(throwable); } if (exclude.add(nested)) { this.cause = new ThrowableProxy(nested, exclude, false); this.cause.commonFrames = ThrowableProxyUtil .findNumberOfCommonFrames(nested.getStackTrace(), stackTraceElementProxyArray); } else { this.cause = new ThrowableProxy(nested, exclude, true); } } if(GET_SUPPRESSED_METHOD != null) { // this will only execute on Java 7 try { Object obj = GET_SUPPRESSED_METHOD.invoke(throwable); if(obj instanceof Throwable[]) { Throwable[] throwableSuppressed = (Throwable[]) obj; if(throwableSuppressed.length > 0) { suppressed = new ThrowableProxy[throwableSuppressed.length]; if (exclude==null) { exclude = createExcludeSet(throwable); } for(int i=0;i<throwableSuppressed.length;i++) { if (exclude.add(throwableSuppressed[i])) { this.suppressed[i] = new ThrowableProxy(throwableSuppressed[i], exclude, false); this.suppressed[i].commonFrames = ThrowableProxyUtil .findNumberOfCommonFrames(throwableSuppressed[i].getStackTrace(), stackTraceElementProxyArray); } else { this.suppressed[i] = new ThrowableProxy(throwableSuppressed[i], exclude, true); } } } } } catch (IllegalAccessException e) { // ignore } catch (InvocationTargetException e) { // ignore } } } else { this.className = "CIRCULAR REFERENCE-" + throwable.getClass().getName(); this.stackTraceElementProxyArray = NO_STACK_TRACE; } } private static Set<Throwable> createExcludeSet(Throwable parent) { Set<Throwable> exclude = Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>()); exclude.add(parent); return exclude; }
Here is a slightly improved version: