-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Consider catching Exception
instead of Throwable
#3826
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider catching Exception
instead of Throwable
#3826
Conversation
@@ -35,18 +35,18 @@ | |||
parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); | |||
} catch(ParserConfigurationException pce) { | |||
// not much point to do anything; could log but... | |||
} catch (Error e) { | |||
} catch (Exception e) { | |||
// 14-Jul-2016, tatu: Not sure how or why, but during code coverage runs | |||
// (via Cobertura) we get `java.lang.AbstractMethodError` so... ignore that too | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 14-Jul-2016, tatu: Not sure how or why, but during code coverage runs
// (via Cobertura) we getjava.lang.AbstractMethodError
so... ignore that too
There was no trace of code coverage tool named Cobertura in databind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why catch Exception though? Remove the Error catching but don't add the Exception handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, let's just remove altogether in this case.But careful with following ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean, keep catching ParserConfigurationException
in line 36 right? Just to be sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep all checks except for the Error check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
@@ -21,7 +21,7 @@ | |||
try { | |||
Class<?> cls = Class.forName("com.fasterxml.jackson.databind.ext.Java7SupportImpl"); | |||
impl = (Java7Support) ClassUtil.createInstance(cls, false); | |||
} catch (Throwable t) { | |||
} catch (Exception | LinkageError t) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we are trying to catch Exceptions or Errors from either Class.forName
or ClassUtil.createInstance
.
Class.forName
throwsLinkageError
/ExceptionInInitializerError
/ClassNotFoundException
are all covered with current changes.- I suppose
ClassUtil.createInstance
should only throwException
or its subclass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave this as-is, unless we can somehow test behavior. My concern is wrt platforms where loading fails, and removing general catch would expose things other than LinkageError
s.
src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java
Show resolved
Hide resolved
@@ -77,11 +78,11 @@ public Path deserialize(JsonParser p, DeserializationContext ctxt) throws IOExce | |||
} | |||
} | |||
return (Path) ctxt.handleInstantiationProblem(handledType(), value, cause); | |||
} catch (Throwable e) { | |||
} catch (Exception | ServiceConfigurationError e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we are after ServiceConfigurationError
thrown by ServiceLoader.load(FileSystemProvider.class)
or any Exception
(for keeping consistency's sake?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's only catch ServiceConfigurationError
. Otherwise I think we'll actually catch whatever handleInstantiationProblem()
usually throws....
I agree catching Throwable is a bad idea. I do fear that getting very specific on the Errors that we catch may miss something. |
@@ -341,7 +341,7 @@ public Object createFromString(DeserializationContext ctxt, String value) throws | |||
if (_fromStringCreator != null) { | |||
try { | |||
return _fromStringCreator.call1(value); | |||
} catch (Throwable t) { | |||
} catch (Exception t) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, these (in this class) make sense.
// 14-Jul-2016, tatu: Not sure how or why, but during code coverage runs | ||
// (via Cobertura) we get `java.lang.AbstractMethodError` so... ignore that too | ||
} | ||
|
||
// [databind#2589] add two more settings just in case | ||
try { | ||
parserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); | ||
} catch (Throwable t) { } // as per previous one, nothing much to do | ||
} catch (Exception t) { } // as per previous one, nothing much to do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case need to leave Exception
like here, for unsupported feature.
(or could consider catching ParserConfigurationException
-- but for now I prefer Exception
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case need to leave Exception like here, for unsupported feature.
I do prefer ParserConfigurationException
for exact same reason because setFeature
method itself is documented to throw ParserConfigurationException
for unsupported feature. Then question becomes "can we trust javax.xml.parsers
and its documentation?" 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. I do not (alas!) trust them NOT to throw, say, IllegalArgumentException
(or NPE as actually documented).
And I say this as maintainer of Woodstox which tries to follow API spec but which still occasional has differed (esp. where spec was incomplete).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception it is then~
@@ -54,7 +54,7 @@ public class OptionalHandlerFactory implements java.io.Serializable | |||
try { | |||
node = org.w3c.dom.Node.class; | |||
doc = org.w3c.dom.Document.class; | |||
} catch (Throwable e) { | |||
} catch (NoClassDefFoundError | Exception e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave exception catching in this particular class as it was; we don't have tests to verify that loading would not fail via Error
s. Even if sort of unlikely, I think LinkageError
etc might occur.
@@ -66,7 +66,7 @@ | |||
Java7Support x = null; | |||
try { | |||
x = Java7Support.instance(); | |||
} catch (Throwable t) { } | |||
} catch (Exception t) { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, leave catching Throwable
as-is.
@@ -1179,7 +1179,7 @@ public static boolean isJDKClass(Class<?> rawType) { | |||
public static boolean isJDK17OrAbove() { | |||
try { | |||
return getJDKMajorVersion() >= 17; | |||
} catch (Throwable t) { | |||
} catch (Exception t) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No real tests to see that this wont start failing; let's leave catching Throwable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in cases where we don't want to make too big a change, could we consider something like the ExceptionUtil I documented in https://medium.com/system-weakness/cwe-248-uncaught-exception-in-java-b6f4ee8daf14 ? Errors like OutOfMemoryError/VirtualMachineError and ThreadDeathError should be rethrown. LinkageError is something that we would need to consider on a case by case basis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we consider something like the ExceptionUtil
Good idea for cases where we are catching Throwable
. --Error
s are do not change quite often, so we may be able to list down most of Error
s and make decisions whether to catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmh. Perhaps for cases where we can determine limits and so on, but allow-listing requires quite a bit of work to get to suitable set.
I think the idea is valid, but I feel not for this particular use case; given that we already catch safely cases during initialization: if we were starting from scratch, I would agree in doing things incrementally. But in this particular case let's keep things simple even if not optimal: I don't want accidental breakages on legacy platforms when there isn't specific problem to fix (as far as I can see).
This is assuming this is more like pro-active maintenance, general idea of trying to avoid catching Throwable
(which I agree with, at general level )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's keep things simple even if not optimal: I don't want accidental breakages on legacy platforms when there isn't specific problem to fix (as far as I can see).
True. And maybe at some point explicit handling of ‘Error’s will be more sound and safe 🧐
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If leaving catch (Throwable t)
cases (same as before) seems off. How about simply "contain" with a single no-op util method? So we can keep track of and write notes about plans? Would look something like
/**
* Util method to keep track of cases where generic `Throwable` is caught.
* https://github.com to keep record of...
*/
public static void keepTrackOfThrowable(Throwable t) {
throw t;
}
Then would be used in our case
try {
return getJDKMajorVersion() >= 17;
} catch (Throwable t) {
keepTrackOfThrowable(t); // <----- here is no-op
System.err.println("Failed to determine JDK major version: "+t);
return false;
}
This solution might seem odd, but will provide better starting point. -- I checked the classes where I reverted back to catching Throwable
, suggested solution above seems doable becasue and all of them simple catch Throwable
and do nothing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, the PR is merged. I mention this conversation on the PR itself so we can always come back and not fresh-start.
@@ -1300,10 +1300,10 @@ public static Method[] getClassMethods(Class<?> cls) | |||
} | |||
try { | |||
return contextClass.getDeclaredMethods(); // Cross fingers | |||
} catch (Throwable t) { | |||
} catch (Exception t) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, I think, can change to only catch Exception
@@ -58,7 +58,7 @@ | |||
+"(\\.\\d+)?" // optional second fractions | |||
+"(Z|[+-]\\d\\d(?:[:]?\\d\\d)?)?" // optional timeoffset/Z | |||
); | |||
} catch (Throwable t) { | |||
} catch (Exception t) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, makes sense.
Ok I think this is a good idea in general. Have concerns about maybe 1/3 of cases: basically dynamic loading of JDK7, and Dom/XML types seems best left catching wider range of things, because we have no good way to test effects and typically testing done during Release Candidate phase is not good at getting feedback on whether usage on, say, Android, or some cloud platforms (Google AppEngine used to be problematic) would suffer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good -- we can always improve more later on; this is a good step forward. Merging.
|
Description
This pull request proposes a change to catch
Exception
instead ofThrowable
in several classes to avoid catchingError
and to catch expected subtypes ofError
explicitly.Changes Made
Notes
Error
incatch
clause or revert the change 👍🏻👍🏻