Class Throwables

java.lang.Object
com.aoapps.lang.Throwables

public final class Throwables extends Object
Utilities for working with Throwable.
  • Method Details

    • isSuppressed

      public static boolean isSuppressed(Throwable t0, Throwable suppressed)
      Checks if a throwable is already suppressed.
    • addSuppressed

      public static Throwable addSuppressed(Throwable t0, Throwable suppressed)
      Adds a suppressed exception, unless already in the list of suppressed exceptions.

      When suppressed is an InterruptedException and t0 is not an InterruptedException, the current thread will be re-interrupted.

      When suppressed is a ThreadDeath and t0 is not itself a ThreadDeath, suppressed will be returned instead, with t0 added to it as suppressed. This is to maintain the precedence of ThreadDeath for fail-fast behavior.

      Parameters:
      t0 - The throwable to add to. When null, suppressed is returned instead.
      suppressed - The suppressed throwable, skipped when null
      Returns:
      t0 when not null, otherwise suppressed.
      See Also:
    • addSuppressedAndThrow

      public static <Ex extends Throwable> void addSuppressedAndThrow(Throwable t0, Class<? extends Ex> exClass, Function<? super Throwable,? extends Ex> exSupplier, Throwable suppressed) throws Error, RuntimeException, Ex
      Adds a suppressed exception, unless already in the list of suppressed exceptions, wrapping when needed, then throwing the result.

      When suppressed is an InterruptedException and t0 is not an InterruptedException, the current thread will be re-interrupted.

      When suppressed is a ThreadDeath and t0 is not itself a ThreadDeath, suppressed will be returned instead, with t0 added to it as suppressed. This is to maintain the precedence of ThreadDeath for fail-fast behavior.

      Only returns when both t0 and suppressed are null.

      Parameters:
      t0 - The throwable to add to. When null, suppressed is thrown instead.
      exClass - Throwables of this class, as well as Error and RuntimeException, are thrown directly.
      exSupplier - Other throwables are wrapped via this function, then thrown
      suppressed - The suppressed throwable, skipped when null
      Throws:
      Error - When resolved throwable is an Error
      RuntimeException - When resolved throwable is a RuntimeException
      Ex - When resolved throwable is an instance of exClass, otherwise wrapped via exSupplier
      See Also:
    • wrap

      public static <Ex extends Throwable> Ex wrap(Throwable t, Class<? extends Ex> exClass, Function<? super Throwable,? extends Ex> exSupplier) throws Error, RuntimeException
      Wraps an exception, unless is an instance of exClass, Error, or RuntimeException.
      1. When null, returns null.
      2. When is an instance of exClass, returns the exception.
      3. When is Error or RuntimeException, throws the exception directly.
      4. Otherwise, throws the exception wrapped via exSupplier.

      This is expected to typically used within a catch block, to throw a narrower scope:

      try {
         …
       } catch (Throwable t) {
         throw Throwables.wrap(t, SQLException.class, SQLException::new);
       }

      When the exception is an InterruptedException and is wrapped via exSupplier, and the resulting wrapper is not itself an InterruptedException, the current thread will be re-interrupted.

      Parameters:
      t - The throwable to return, throw, or wrap and return.
      exClass - Throwables of this class are returned directly.
      exSupplier - Throwables that a not returned directly, and are not Error or RuntimeException, are wrapped via this function, then returned.
      Returns:
      t when is an instance of exClass or when t has been wrapped via exSupplier.
      Throws:
      Error - When t is an Error
      RuntimeException - When t is a RuntimeException
      See Also:
    • newSurrogate

      public static <Ex extends Throwable> Ex newSurrogate(Ex template, Throwable cause)

      Attempts to create a new instance of the same class as the given template Throwable, with all important state maintained, but with the stack trace of the current Thread. When a new throwable is created, it will use the given cause, possibly with additional wrapping for compatibility.

      This is used to maintain exception types and states across thread boundaries, such as when an exception cause is obtained from an ExecutionException. By wrapping the template, the full stack traces of both threads are maintained. This new Throwable provides the full stack trace of the caller, while the template contains the stack trace from the other thread.

      Only types with registered factories will perform the conversion, otherwise the given cause is returned without wrapping.

      This current implementation has registered all possible Java SE 8 throwable types, except those that have been removed through Java 17. Additionally, various throwable implementations register themselves in static blocks, while other APIs may be registered via the ServiceLoader mechanism on the ThrowableSurrogateFactoryInitializer interface.

      Parameters:
      cause - The cause to use for the new throwable. This should typically be either the template itself, or should have the template somewhere in its chain of causes.
      Returns:
      When wrapping performed, returns a new throwable of the same class as the template, but with the caller's stack trace and the given cause. When no wrapping performed, returns the template itself.
      See Also:
    • newSurrogate

      public static <Ex extends Throwable> Ex newSurrogate(Ex template)

      Attempts to create a new instance of the same class as the given template Throwable, with all important state maintained, but with the stack trace of the current Thread. When a new throwable is created, the template will be used as its cause, possibly with additional wrapping for compatibility.

      This is used to maintain exception types and states across thread boundaries, such as when an exception cause is obtained from an ExecutionException. By wrapping the template, the full stack traces of both threads are maintained. This new Throwable provides the full stack trace of the caller, while the template contains the stack trace from the other thread.

      Only types with registered factories will perform the conversion, otherwise the given cause is returned without wrapping.

      This current implementation has registered all possible Java SE 8 throwable types, except those that have been removed through Java 17. Additionally, various throwable implementations register themselves in static blocks, while other APIs may be registered via the ServiceLoader mechanism on the ThrowableSurrogateFactoryInitializer interface.

      Returns:
      When wrapping performed, returns a new throwable of the same class as the template, but with the caller's stack trace and the template as a cause. When no wrapping performed, returns the template itself.
      See Also:
    • registerSurrogateFactory

      public static <Ex extends Throwable> void registerSurrogateFactory(Class<Ex> exClass, ThrowableSurrogateFactory<Ex> factory)
      Registers a new throwable surrogate factory for a given type.