Improve Invoker exception messages #3133
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Some of the exception messages you can get from calling an Invoker with the wrong arguments are a bit obtuse and I wanted to look at providing a bit more information.
To do this, I'm doing extra checks before calling the method to ensure that:
Most of these checks have to be done before the argument array is spread to the actual arguments, since the MethodHandles implementation will throw an exception there if things are the wrong types.
If there are transformers, type checking is done against the input type of the transformer.
The null check for the instance is done after the transformers run because an instance transformer can convert a
null
to a real instance.The null check for primitive arguments, however, has to be done before the argument array is spread, since the spread operation will fail if the arguments cannot be converted to the primitive type successfully. I think this is safe because we separately check that the types for an argument transformer match the method parameters, and if that's a primitive type then the argument transformer isn't able to return
null
there.Performance
I'm doing all of these checks before method invocation. Running an invoke call to
InvokableBean.ping
10 million times took 5.2 seconds before these changes and 5.7 seconds afterwards, so there is a performance impact there which we may want to look into further.One other thought I had was that it might be possible to catch
NullPointerException
andClassCastException
and only do these checks in the case where one of those exceptions was thrown. If we find that there's a problem with the instance or arguments at that point, we can replace the exception thrown by the MethodHandles implementation. If all our checks pass we'd rethrow the original exception.Examples
Not enough arguments:
Before:
After:
Arguments array is
null
when arguments are requiredBefore:
After:
^I wasn't sure whether this one should still be a
NullPointerException
or whether we should treat it the same as when the user doesn't pass enough arguments.Primitive argument is null:
Before:
After:
Primitive argument has the wrong type:
Before:
After:
Instance has the wrong type:
Before:
After:
Null instance for a non-static method:
Before:
After: