diff --git a/akka-actor-tests/src/test/java/akka/japi/ThrowablesTest.java b/akka-actor-tests/src/test/java/akka/japi/ThrowablesTest.java new file mode 100644 index 0000000000..11a99d7c6f --- /dev/null +++ b/akka-actor-tests/src/test/java/akka/japi/ThrowablesTest.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2014-2018 Lightbend Inc. + */ +package akka.japi; + +import org.junit.Assert; +import org.junit.Test; +import scala.util.control.ControlThrowable; + +public class ThrowablesTest { + @Test + public void testIsNonFatal(){ + Assert.assertTrue(Throwables.isNonFatal(new IllegalArgumentException("isNonFatal"))); + } + + private static class ControlThrowableImpl extends Throwable implements ControlThrowable{} + + @Test + public void testIsFatal(){ + Assert.assertTrue(Throwables.isFatal(new StackOverflowError("fatal"))); + Assert.assertTrue(Throwables.isFatal(new ThreadDeath())); + Assert.assertTrue(Throwables.isFatal(new InterruptedException("fatal"))); + Assert.assertTrue(Throwables.isFatal(new LinkageError("fatal"))); + Assert.assertTrue(Throwables.isFatal(new ControlThrowableImpl())); + } +} diff --git a/akka-actor/src/main/scala/akka/japi/Throwables.scala b/akka-actor/src/main/scala/akka/japi/Throwables.scala new file mode 100644 index 0000000000..f82829bd0d --- /dev/null +++ b/akka-actor/src/main/scala/akka/japi/Throwables.scala @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2009-2018 Lightbend Inc. + */ +package akka.japi + +import scala.util.control.NonFatal + +/** + * Helper class for determining whether a `Throwable` is fatal or not. + * User should only catch the non-fatal one,and keep rethrow the fatal one. + * + * Fatal errors are errors like `VirtualMachineError` + * (for example, `OutOfMemoryError` and `StackOverflowError`, subclasses of `VirtualMachineError`), `ThreadDeath`, + * `LinkageError`, `InterruptedException`, `ControlThrowable`. + * + * Note. this helper keep the same semantic with `NonFatal` in Scala. + * For example, all harmless `Throwable`s can be caught by: + * {{{ + * try { + * // dangerous stuff + * } catch(Throwable e) { + * if (Throwables.isNonFatal(e)){ + * log.error(e, "Something not that bad."); + * } else { + * throw e; + * } + * }}} + */ +object Throwables { + /** + * Returns true if the provided `Throwable` is to be considered non-fatal, + * or false if it is to be considered fatal + */ + def isNonFatal(throwable: Throwable): Boolean = NonFatal(throwable) + + /** + * Returns true if the provided `Throwable` is to be considered fatal, + * or false if it is to be considered non-fatal + */ + def isFatal(throwable: Throwable): Boolean = !isNonFatal(throwable) +}