public static Class<?> getCallerClass(final int depth) { if (depth < 0) { throw new IndexOutOfBoundsException(Integer.toString(depth)); } // note that we need to add 1 to the depth value to compensate for this method, but not for the Method.invoke // since Reflection.getCallerClass ignores the call to Method.invoke() if (supportsFastReflection()) { try { return (Class<?>) GET_CALLER_CLASS.invoke(null, depth + 1 + JDK_7u25_OFFSET); } catch (final Exception e) { // theoretically this could happen if the caller class were native code LOGGER.error("Error in ReflectionUtil.getCallerClass({}).", depth, e); // TODO: return Object.class return null; } } // TODO: SecurityManager-based version? // slower fallback method using stack trace final StackTraceElement element = getEquivalentStackTraceElement(depth + 1); try { return LoaderUtil.loadClass(element.getClassName()); } catch (final ClassNotFoundException e) { LOGGER.error("Could not find class in ReflectionUtil.getCallerClass({}).", depth, e); } // TODO: return Object.class return null; }
/** * Has no effect on Java 6 and below. * * @param throwable a Throwable * @return see Java 7's {@link Throwable# getSuppressed()} * @see Throwable# getSuppressed() * @ deprecated If compiling on Java 7 and above use {@link Throwable# getSuppressed()}. Marked as deprecated because * Java 6 is deprecated. */ //@Deprecated public static Throwable[] getSuppressed(final Throwable throwable) { if (GET_SUPPRESSED != null) { try { return (Throwable[]) GET_SUPPRESSED.invoke(throwable); } catch (final Exception e) { // Only happens on Java >= 7 if this class has a bug. StatusLogger.getLogger().error(e); return null; } } return null; }
private ThrowableProxy[] toSuppressedProxies(final Throwable thrown) { try { final Throwable[] suppressed = Throwables.getSuppressed(thrown); if (suppressed == null) { return EMPTY_THROWABLE_PROXY_ARRAY; } final ThrowableProxy[] proxies = new ThrowableProxy[suppressed.length]; for (int i = 0; i < suppressed.length; i++) { proxies[i] = new ThrowableProxy(suppressed[i]); } return proxies; } catch (final Exception e) { StatusLogger.getLogger().error(e); } return EMPTY_THROWABLE_PROXY_ARRAY; } }
static StackTraceElement getEquivalentStackTraceElement(final int depth) { // (MS) I tested the difference between using Throwable.getStackTrace() and Thread.getStackTrace(), and // the version using Throwable was surprisingly faster! at least on Java 1.8. See ReflectionBenchmark. final StackTraceElement[] elements = new Throwable().getStackTrace(); int i = 0; for (final StackTraceElement element : elements) { if (isValid(element)) { if (i == depth) { return element; } else { ++i; } } } LOGGER.error("Could not find an appropriate StackTraceElement at index {}", depth); throw new IndexOutOfBoundsException(Integer.toString(depth)); }