Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.ExceptionUtil;

/**
* To support Java7-incomplete platforms, we will offer support for JDK 7
Expand All @@ -25,6 +26,7 @@ public abstract class Java7Support
// 09-Sep-2019, tatu: Used to log earlier, but with 2.10.0 let's not log
// java.util.logging.Logger.getLogger(Java7Support.class.getName())
// .warning("Unable to load JDK7 annotations (@ConstructorProperties, @Transient): no Java7 annotation support added");
ExceptionUtil.rethrowIfFatal(t);
}
IMPL = impl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.fasterxml.jackson.databind.ser.Serializers;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.ExceptionUtil;

/**
* Helper class used for isolating details of handling optional+external types
Expand Down Expand Up @@ -55,6 +56,7 @@ public class OptionalHandlerFactory implements java.io.Serializable
node = org.w3c.dom.Node.class;
doc = org.w3c.dom.Document.class;
} catch (Throwable e) {
ExceptionUtil.rethrowIfFatal(e);
// not optimal but will do
// 02-Nov-2020, Xakep_SDK: Remove java.logging module dependency
// Logger.getLogger(OptionalHandlerFactory.class.getName())
Expand All @@ -73,7 +75,9 @@ public class OptionalHandlerFactory implements java.io.Serializable
Java7Handlers x = null;
try {
x = Java7Handlers.instance();
} catch (Throwable t) { }
} catch (Throwable t) {
ExceptionUtil.rethrowIfFatal(t);
}
_jdk7Helper = x;
}

Expand Down Expand Up @@ -232,6 +236,7 @@ private Object instantiate(String className, JavaType valueType)
try {
return instantiate(Class.forName(className), valueType);
} catch (Throwable e) {
ExceptionUtil.rethrowIfFatal(e);
throw new IllegalStateException("Failed to find class `"
+className+"` for handling values of type "+ClassUtil.getTypeDescription(valueType)
+", problem: ("+e.getClass().getName()+") "+e.getMessage());
Expand All @@ -243,6 +248,7 @@ private Object instantiate(Class<?> handlerClass, JavaType valueType)
try {
return ClassUtil.createInstance(handlerClass, false);
} catch (Throwable e) {
ExceptionUtil.rethrowIfFatal(e);
throw new IllegalStateException("Failed to create instance of `"
+handlerClass.getName()+"` for handling values of type "+ClassUtil.getTypeDescription(valueType)
+", problem: ("+e.getClass().getName()+") "+e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ public class JacksonAnnotationIntrospector
Java7Support x = null;
try {
x = Java7Support.instance();
} catch (Throwable t) { }
} catch (Throwable t) {
ExceptionUtil.rethrowIfFatal(t);
}
_java7Helper = x;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,7 @@ public static boolean isJDK17OrAbove() {
try {
return getJDKMajorVersion() >= 17;
} catch (Throwable t) {
ExceptionUtil.rethrowIfFatal(t);
System.err.println("Failed to determine JDK major version, assuming pre-JDK-17; problem: "+t);
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.fasterxml.jackson.databind.util;

/**
* Utility methods for dealing with exceptions/throwables
*
* @since 2.15
*/
public class ExceptionUtil {
private ExceptionUtil() {}

/**
* It is important never to catch all <code>Throwable</code>s. Some like
* {@link InterruptedException} should be rethrown. Based on
* <a href="https://www.scala-lang.org/api/2.13.10/scala/util/control/NonFatal$.html">scala.util.control.NonFatal</a>.
*
* This method should be used with care.
* <p>
* If the <code>Throwable</code> is fatal, it is rethrown, otherwise, this method just returns.
* The input throwable is thrown if it is an <code>Error</code> or a <code>RuntimeException</code>.
* Otherwise, the method wraps the throwable in a RuntimeException and throws that.
* </p>
*
* @param throwable to check
* @throws Error the input throwable if it is fatal
* @throws RuntimeException the input throwable if it is fatal - throws the original throwable
* if is a <code>RuntimeException</code>. Otherwise, wraps the throwable in a RuntimeException.
*/
public static void rethrowIfFatal(Throwable throwable) throws Error, RuntimeException {
if (isFatal(throwable)) {
if (throwable instanceof Error) {
throw (Error) throwable;
}
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
}
throw new RuntimeException(throwable);
}
}

/**
* It is important never to catch all <code>Throwable</code>s. Some like
* {@link InterruptedException} should be rethrown. Based on
* <a href="https://www.scala-lang.org/api/2.13.10/scala/util/control/NonFatal$.html">scala.util.control.NonFatal</a>.
*
* @param throwable to check
* @return whether the <code>Throwable</code> is a fatal error
*/
private static boolean isFatal(Throwable throwable) {
return (throwable instanceof VirtualMachineError
|| throwable instanceof ThreadDeath
|| throwable instanceof InterruptedException
|| throwable instanceof ClassCircularityError
|| throwable instanceof ClassFormatError
|| throwable instanceof IncompatibleClassChangeError
|| throwable instanceof BootstrapMethodError
|| throwable instanceof VerifyError
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.fasterxml.jackson.databind.util;

import com.fasterxml.jackson.databind.BaseTest;

public class ExceptionUtilTest extends BaseTest {
public void testNoClassDefError() {
//next line should be a no-op
ExceptionUtil.rethrowIfFatal(new NoClassDefFoundError("fake"));
}

public void testExceptionInInitializerError() {
//next line should be a no-op
ExceptionUtil.rethrowIfFatal(new ExceptionInInitializerError("fake"));
}

public void testOutOfMemoryError() {
try {
ExceptionUtil.rethrowIfFatal(new OutOfMemoryError("fake"));
fail("expected OutOfMemoryError");
} catch (OutOfMemoryError err) {
assertEquals("fake", err.getMessage());
}
}

public void testVerifyError() {
try {
ExceptionUtil.rethrowIfFatal(new VerifyError("fake"));
fail("expected VerifyError");
} catch (VerifyError err) {
assertEquals("fake", err.getMessage());
}
}
}