Coverage Summary for Class: Throwables (com.google.common.base)

Class Method, % Line, %
Throwables 18.2% (4/22) 13% (12/92)
Throwables$1 0% (0/3) 0% (0/7)
Total 16% (4/25) 12.1% (12/99)


1 /* 2  * Copyright (C) 2007 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5  * in compliance with the License. You may obtain a copy of the License at 6  * 7  * http://www.apache.org/licenses/LICENSE-2.0 8  * 9  * Unless required by applicable law or agreed to in writing, software distributed under the License 10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11  * or implied. See the License for the specific language governing permissions and limitations under 12  * the License. 13  */ 14  15 package com.google.common.base; 16  17 import static com.google.common.base.Preconditions.checkNotNull; 18 import static java.util.Arrays.asList; 19 import static java.util.Collections.unmodifiableList; 20 import static java.util.Objects.requireNonNull; 21  22 import com.google.common.annotations.Beta; 23 import com.google.common.annotations.GwtCompatible; 24 import com.google.common.annotations.GwtIncompatible; 25 import com.google.common.annotations.VisibleForTesting; 26 import com.google.errorprone.annotations.CanIgnoreReturnValue; 27 import java.io.IOException; 28 import java.io.PrintWriter; 29 import java.io.StringWriter; 30 import java.lang.reflect.InvocationTargetException; 31 import java.lang.reflect.Method; 32 import java.util.AbstractList; 33 import java.util.ArrayList; 34 import java.util.Collections; 35 import java.util.List; 36 import javax.annotation.CheckForNull; 37  38 /** 39  * Static utility methods pertaining to instances of {@link Throwable}. 40  * 41  * <p>See the Guava User Guide entry on <a 42  * href="https://github.com/google/guava/wiki/ThrowablesExplained">Throwables</a>. 43  * 44  * @author Kevin Bourrillion 45  * @author Ben Yu 46  * @since 1.0 47  */ 48 @GwtCompatible(emulated = true) 49 // TODO(b/147136275): After adding @CheckForNull below, add @ElementTypesAreNonnullByDefault. 50 public final class Throwables { 51  private Throwables() {} 52  53  /** 54  * Throws {@code throwable} if it is an instance of {@code declaredType}. Example usage: 55  * 56  * <pre> 57  * for (Foo foo : foos) { 58  * try { 59  * foo.bar(); 60  * } catch (BarException | RuntimeException | Error t) { 61  * failure = t; 62  * } 63  * } 64  * if (failure != null) { 65  * throwIfInstanceOf(failure, BarException.class); 66  * throwIfUnchecked(failure); 67  * throw new AssertionError(failure); 68  * } 69  * </pre> 70  * 71  * @since 20.0 72  */ 73  @GwtIncompatible // Class.cast, Class.isInstance 74  public static <X extends Throwable> void throwIfInstanceOf( 75  Throwable throwable, Class<X> declaredType) throws X { 76  checkNotNull(throwable); 77  if (declaredType.isInstance(throwable)) { 78  throw declaredType.cast(throwable); 79  } 80  } 81  82  /** 83  * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@code 84  * declaredType}. Example usage: 85  * 86  * <pre> 87  * try { 88  * someMethodThatCouldThrowAnything(); 89  * } catch (IKnowWhatToDoWithThisException e) { 90  * handle(e); 91  * } catch (Throwable t) { 92  * Throwables.propagateIfInstanceOf(t, IOException.class); 93  * Throwables.propagateIfInstanceOf(t, SQLException.class); 94  * throw Throwables.propagate(t); 95  * } 96  * </pre> 97  * 98  * @deprecated Use {@link #throwIfInstanceOf}, which has the same behavior but rejects {@code 99  * null}. 100  */ 101  @Deprecated 102  @GwtIncompatible // throwIfInstanceOf 103  public static <X extends Throwable> void propagateIfInstanceOf( 104  @CheckForNull Throwable throwable, Class<X> declaredType) throws X { 105  if (throwable != null) { 106  throwIfInstanceOf(throwable, declaredType); 107  } 108  } 109  110  /** 111  * Throws {@code throwable} if it is a {@link RuntimeException} or {@link Error}. Example usage: 112  * 113  * <pre> 114  * for (Foo foo : foos) { 115  * try { 116  * foo.bar(); 117  * } catch (RuntimeException | Error t) { 118  * failure = t; 119  * } 120  * } 121  * if (failure != null) { 122  * throwIfUnchecked(failure); 123  * throw new AssertionError(failure); 124  * } 125  * </pre> 126  * 127  * @since 20.0 128  */ 129  public static void throwIfUnchecked(Throwable throwable) { 130  checkNotNull(throwable); 131  if (throwable instanceof RuntimeException) { 132  throw (RuntimeException) throwable; 133  } 134  if (throwable instanceof Error) { 135  throw (Error) throwable; 136  } 137  } 138  139  /** 140  * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link 141  * RuntimeException} or {@link Error}. Example usage: 142  * 143  * <pre> 144  * try { 145  * someMethodThatCouldThrowAnything(); 146  * } catch (IKnowWhatToDoWithThisException e) { 147  * handle(e); 148  * } catch (Throwable t) { 149  * Throwables.propagateIfPossible(t); 150  * throw new RuntimeException("unexpected", t); 151  * } 152  * </pre> 153  * 154  * @deprecated Use {@link #throwIfUnchecked}, which has the same behavior but rejects {@code 155  * null}. 156  */ 157  @Deprecated 158  @GwtIncompatible 159  public static void propagateIfPossible(@CheckForNull Throwable throwable) { 160  if (throwable != null) { 161  throwIfUnchecked(throwable); 162  } 163  } 164  165  /** 166  * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link 167  * RuntimeException}, {@link Error}, or {@code declaredType}. Example usage: 168  * 169  * <pre> 170  * try { 171  * someMethodThatCouldThrowAnything(); 172  * } catch (IKnowWhatToDoWithThisException e) { 173  * handle(e); 174  * } catch (Throwable t) { 175  * Throwables.propagateIfPossible(t, OtherException.class); 176  * throw new RuntimeException("unexpected", t); 177  * } 178  * </pre> 179  * 180  * @param throwable the Throwable to possibly propagate 181  * @param declaredType the single checked exception type declared by the calling method 182  */ 183  @GwtIncompatible // propagateIfInstanceOf 184  public static <X extends Throwable> void propagateIfPossible( 185  @CheckForNull Throwable throwable, Class<X> declaredType) throws X { 186  propagateIfInstanceOf(throwable, declaredType); 187  propagateIfPossible(throwable); 188  } 189  190  /** 191  * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link 192  * RuntimeException}, {@link Error}, {@code declaredType1}, or {@code declaredType2}. In the 193  * unlikely case that you have three or more declared checked exception types, you can handle them 194  * all by invoking these methods repeatedly. See usage example in {@link 195  * #propagateIfPossible(Throwable, Class)}. 196  * 197  * @param throwable the Throwable to possibly propagate 198  * @param declaredType1 any checked exception type declared by the calling method 199  * @param declaredType2 any other checked exception type declared by the calling method 200  */ 201  @GwtIncompatible // propagateIfInstanceOf 202  public static <X1 extends Throwable, X2 extends Throwable> void propagateIfPossible( 203  @CheckForNull Throwable throwable, Class<X1> declaredType1, Class<X2> declaredType2) 204  throws X1, X2 { 205  checkNotNull(declaredType2); 206  propagateIfInstanceOf(throwable, declaredType1); 207  propagateIfPossible(throwable, declaredType2); 208  } 209  210  /** 211  * Propagates {@code throwable} as-is if it is an instance of {@link RuntimeException} or {@link 212  * Error}, or else as a last resort, wraps it in a {@code RuntimeException} and then propagates. 213  * 214  * <p>This method always throws an exception. The {@code RuntimeException} return type allows 215  * client code to signal to the compiler that statements after the call are unreachable. Example 216  * usage: 217  * 218  * <pre> 219  * T doSomething() { 220  * try { 221  * return someMethodThatCouldThrowAnything(); 222  * } catch (IKnowWhatToDoWithThisException e) { 223  * return handle(e); 224  * } catch (Throwable t) { 225  * throw Throwables.propagate(t); 226  * } 227  * } 228  * </pre> 229  * 230  * @param throwable the Throwable to propagate 231  * @return nothing will ever be returned; this return type is only for your convenience, as 232  * illustrated in the example above 233  * @deprecated Use {@code throw e} or {@code throw new RuntimeException(e)} directly, or use a 234  * combination of {@link #throwIfUnchecked} and {@code throw new RuntimeException(e)}. For 235  * background on the deprecation, read <a href="https://goo.gl/Ivn2kc">Why we deprecated 236  * {@code Throwables.propagate}</a>. 237  */ 238  @CanIgnoreReturnValue 239  @GwtIncompatible 240  @Deprecated 241  public static RuntimeException propagate(Throwable throwable) { 242  throwIfUnchecked(throwable); 243  throw new RuntimeException(throwable); 244  } 245  246  /** 247  * Returns the innermost cause of {@code throwable}. The first throwable in a chain provides 248  * context from when the error or exception was initially detected. Example usage: 249  * 250  * <pre> 251  * assertEquals("Unable to assign a customer id", Throwables.getRootCause(e).getMessage()); 252  * </pre> 253  * 254  * @throws IllegalArgumentException if there is a loop in the causal chain 255  */ 256  public static Throwable getRootCause(Throwable throwable) { 257  // Keep a second pointer that slowly walks the causal chain. If the fast pointer ever catches 258  // the slower pointer, then there's a loop. 259  Throwable slowPointer = throwable; 260  boolean advanceSlowPointer = false; 261  262  Throwable cause; 263  while ((cause = throwable.getCause()) != null) { 264  throwable = cause; 265  266  if (throwable == slowPointer) { 267  throw new IllegalArgumentException("Loop in causal chain detected.", throwable); 268  } 269  if (advanceSlowPointer) { 270  slowPointer = slowPointer.getCause(); 271  } 272  advanceSlowPointer = !advanceSlowPointer; // only advance every other iteration 273  } 274  return throwable; 275  } 276  277  /** 278  * Gets a {@code Throwable} cause chain as a list. The first entry in the list will be {@code 279  * throwable} followed by its cause hierarchy. Note that this is a snapshot of the cause chain and 280  * will not reflect any subsequent changes to the cause chain. 281  * 282  * <p>Here's an example of how it can be used to find specific types of exceptions in the cause 283  * chain: 284  * 285  * <pre> 286  * Iterables.filter(Throwables.getCausalChain(e), IOException.class)); 287  * </pre> 288  * 289  * @param throwable the non-null {@code Throwable} to extract causes from 290  * @return an unmodifiable list containing the cause chain starting with {@code throwable} 291  * @throws IllegalArgumentException if there is a loop in the causal chain 292  */ 293  @Beta // TODO(kevinb): decide best return type 294  public static List<Throwable> getCausalChain(Throwable throwable) { 295  checkNotNull(throwable); 296  List<Throwable> causes = new ArrayList<>(4); 297  causes.add(throwable); 298  299  // Keep a second pointer that slowly walks the causal chain. If the fast pointer ever catches 300  // the slower pointer, then there's a loop. 301  Throwable slowPointer = throwable; 302  boolean advanceSlowPointer = false; 303  304  Throwable cause; 305  while ((cause = throwable.getCause()) != null) { 306  throwable = cause; 307  causes.add(throwable); 308  309  if (throwable == slowPointer) { 310  throw new IllegalArgumentException("Loop in causal chain detected.", throwable); 311  } 312  if (advanceSlowPointer) { 313  slowPointer = slowPointer.getCause(); 314  } 315  advanceSlowPointer = !advanceSlowPointer; // only advance every other iteration 316  } 317  return Collections.unmodifiableList(causes); 318  } 319  320  /** 321  * Returns {@code throwable}'s cause, cast to {@code expectedCauseType}. 322  * 323  * <p>Prefer this method instead of manually casting an exception's cause. For example, {@code 324  * (IOException) e.getCause()} throws a {@link ClassCastException} that discards the original 325  * exception {@code e} if the cause is not an {@link IOException}, but {@code 326  * Throwables.getCauseAs(e, IOException.class)} keeps {@code e} as the {@link 327  * ClassCastException}'s cause. 328  * 329  * @throws ClassCastException if the cause cannot be cast to the expected type. The {@code 330  * ClassCastException}'s cause is {@code throwable}. 331  * @since 22.0 332  */ 333  @Beta 334  @GwtIncompatible // Class.cast(Object) 335  @SuppressWarnings("nullness") 336  // TODO(b/147136275): After updating callers, add @CheckForNull, and remove @SuppressWarnings. 337  public static <X extends Throwable> X getCauseAs( 338  Throwable throwable, Class<X> expectedCauseType) { 339  try { 340  return expectedCauseType.cast(throwable.getCause()); 341  } catch (ClassCastException e) { 342  e.initCause(throwable); 343  throw e; 344  } 345  } 346  347  /** 348  * Returns a string containing the result of {@link Throwable#toString() toString()}, followed by 349  * the full, recursive stack trace of {@code throwable}. Note that you probably should not be 350  * parsing the resulting string; if you need programmatic access to the stack frames, you can call 351  * {@link Throwable#getStackTrace()}. 352  */ 353  @GwtIncompatible // java.io.PrintWriter, java.io.StringWriter 354  public static String getStackTraceAsString(Throwable throwable) { 355  StringWriter stringWriter = new StringWriter(); 356  throwable.printStackTrace(new PrintWriter(stringWriter)); 357  return stringWriter.toString(); 358  } 359  360  /** 361  * Returns the stack trace of {@code throwable}, possibly providing slower iteration over the full 362  * trace but faster iteration over parts of the trace. Here, "slower" and "faster" are defined in 363  * comparison to the normal way to access the stack trace, {@link Throwable#getStackTrace() 364  * throwable.getStackTrace()}. Note, however, that this method's special implementation is not 365  * available for all platforms and configurations. If that implementation is unavailable, this 366  * method falls back to {@code getStackTrace}. Callers that require the special implementation can 367  * check its availability with {@link #lazyStackTraceIsLazy()}. 368  * 369  * <p>The expected (but not guaranteed) performance of the special implementation differs from 370  * {@code getStackTrace} in one main way: The {@code lazyStackTrace} call itself returns quickly 371  * by delaying the per-stack-frame work until each element is accessed. Roughly speaking: 372  * 373  * <ul> 374  * <li>{@code getStackTrace} takes {@code stackSize} time to return but then negligible time to 375  * retrieve each element of the returned list. 376  * <li>{@code lazyStackTrace} takes negligible time to return but then {@code 1/stackSize} time 377  * to retrieve each element of the returned list (probably slightly more than {@code 378  * 1/stackSize}). 379  * </ul> 380  * 381  * <p>Note: The special implementation does not respect calls to {@link Throwable#setStackTrace 382  * throwable.setStackTrace}. Instead, it always reflects the original stack trace from the 383  * exception's creation. 384  * 385  * @since 19.0 386  */ 387  // TODO(cpovirk): Say something about the possibility that List access could fail at runtime? 388  @Beta 389  @GwtIncompatible // lazyStackTraceIsLazy, jlaStackTrace 390  // TODO(cpovirk): Consider making this available under GWT (slow implementation only). 391  public static List<StackTraceElement> lazyStackTrace(Throwable throwable) { 392  return lazyStackTraceIsLazy() 393  ? jlaStackTrace(throwable) 394  : unmodifiableList(asList(throwable.getStackTrace())); 395  } 396  397  /** 398  * Returns whether {@link #lazyStackTrace} will use the special implementation described in its 399  * documentation. 400  * 401  * @since 19.0 402  */ 403  @Beta 404  @GwtIncompatible // getStackTraceElementMethod 405  public static boolean lazyStackTraceIsLazy() { 406  return getStackTraceElementMethod != null && getStackTraceDepthMethod != null; 407  } 408  409  @GwtIncompatible // invokeAccessibleNonThrowingMethod 410  private static List<StackTraceElement> jlaStackTrace(final Throwable t) { 411  checkNotNull(t); 412  /* 413  * TODO(cpovirk): Consider optimizing iterator() to catch IOOBE instead of doing bounds checks. 414  * 415  * TODO(cpovirk): Consider the UnsignedBytes pattern if it performs faster and doesn't cause 416  * AOSP grief. 417  */ 418  return new AbstractList<StackTraceElement>() { 419  /* 420  * The following requireNonNull calls are safe because we use jlaStackTrace() only if 421  * lazyStackTraceIsLazy() returns true. 422  */ 423  @Override 424  public StackTraceElement get(int n) { 425  return (StackTraceElement) 426  invokeAccessibleNonThrowingMethod( 427  requireNonNull(getStackTraceElementMethod), requireNonNull(jla), t, n); 428  } 429  430  @Override 431  public int size() { 432  return (Integer) 433  invokeAccessibleNonThrowingMethod( 434  requireNonNull(getStackTraceDepthMethod), requireNonNull(jla), t); 435  } 436  }; 437  } 438  439  @GwtIncompatible // java.lang.reflect 440  private static Object invokeAccessibleNonThrowingMethod( 441  Method method, Object receiver, Object... params) { 442  try { 443  return method.invoke(receiver, params); 444  } catch (IllegalAccessException e) { 445  throw new RuntimeException(e); 446  } catch (InvocationTargetException e) { 447  throw propagate(e.getCause()); 448  } 449  } 450  451  /** JavaLangAccess class name to load using reflection */ 452  @GwtIncompatible // not used by GWT emulation 453  private static final String JAVA_LANG_ACCESS_CLASSNAME = "sun.misc.JavaLangAccess"; 454  455  /** SharedSecrets class name to load using reflection */ 456  @GwtIncompatible // not used by GWT emulation 457  @VisibleForTesting 458  static final String SHARED_SECRETS_CLASSNAME = "sun.misc.SharedSecrets"; 459  460  /** Access to some fancy internal JVM internals. */ 461  @GwtIncompatible // java.lang.reflect 462  @CheckForNull 463  private static final Object jla = getJLA(); 464  465  /** 466  * The "getStackTraceElementMethod" method, only available on some JDKs so we use reflection to 467  * find it when available. When this is null, use the slow way. 468  */ 469  @GwtIncompatible // java.lang.reflect 470  @CheckForNull 471  private static final Method getStackTraceElementMethod = (jla == null) ? null : getGetMethod(); 472  473  /** 474  * The "getStackTraceDepth" method, only available on some JDKs so we use reflection to find it 475  * when available. When this is null, use the slow way. 476  */ 477  @GwtIncompatible // java.lang.reflect 478  @CheckForNull 479  private static final Method getStackTraceDepthMethod = (jla == null) ? null : getSizeMethod(jla); 480  481  /** 482  * Returns the JavaLangAccess class that is present in all Sun JDKs. It is not allowed in 483  * AppEngine, and not present in non-Sun JDKs. 484  */ 485  @GwtIncompatible // java.lang.reflect 486  @CheckForNull 487  private static Object getJLA() { 488  try { 489  /* 490  * We load sun.misc.* classes using reflection since Android doesn't support these classes and 491  * would result in compilation failure if we directly refer to these classes. 492  */ 493  Class<?> sharedSecrets = Class.forName(SHARED_SECRETS_CLASSNAME, false, null); 494  Method langAccess = sharedSecrets.getMethod("getJavaLangAccess"); 495  return langAccess.invoke(null); 496  } catch (ThreadDeath death) { 497  throw death; 498  } catch (Throwable t) { 499  /* 500  * This is not one of AppEngine's allowed classes, so even in Sun JDKs, this can fail with 501  * a NoClassDefFoundError. Other apps might deny access to sun.misc packages. 502  */ 503  return null; 504  } 505  } 506  507  /** 508  * Returns the Method that can be used to resolve an individual StackTraceElement, or null if that 509  * method cannot be found (it is only to be found in fairly recent JDKs). 510  */ 511  @GwtIncompatible // java.lang.reflect 512  @CheckForNull 513  private static Method getGetMethod() { 514  return getJlaMethod("getStackTraceElement", Throwable.class, int.class); 515  } 516  517  /** 518  * Returns the Method that can be used to return the size of a stack, or null if that method 519  * cannot be found (it is only to be found in fairly recent JDKs). Tries to test method {@link 520  * sun.misc.JavaLangAccess#getStackTraceDepth(Throwable)} getStackTraceDepth} prior to return it 521  * (might fail some JDKs). 522  * 523  * <p>See <a href="https://github.com/google/guava/issues/2887">Throwables#lazyStackTrace throws 524  * UnsupportedOperationException</a>. 525  */ 526  @GwtIncompatible // java.lang.reflect 527  @CheckForNull 528  private static Method getSizeMethod(Object jla) { 529  try { 530  Method getStackTraceDepth = getJlaMethod("getStackTraceDepth", Throwable.class); 531  if (getStackTraceDepth == null) { 532  return null; 533  } 534  getStackTraceDepth.invoke(jla, new Throwable()); 535  return getStackTraceDepth; 536  } catch (UnsupportedOperationException | IllegalAccessException | InvocationTargetException e) { 537  return null; 538  } 539  } 540  541  @GwtIncompatible // java.lang.reflect 542  @CheckForNull 543  private static Method getJlaMethod(String name, Class<?>... parameterTypes) throws ThreadDeath { 544  try { 545  return Class.forName(JAVA_LANG_ACCESS_CLASSNAME, false, null).getMethod(name, parameterTypes); 546  } catch (ThreadDeath death) { 547  throw death; 548  } catch (Throwable t) { 549  /* 550  * Either the JavaLangAccess class itself is not found, or the method is not supported on the 551  * JVM. 552  */ 553  return null; 554  } 555  } 556 }