undeclaredThrowableException API
UndeclaredThrowableException直译过来,就是未声明的throwable型异常,我们看它的api
如果代理实例的调用处理程序的 invoke 方法抛出一个经过检查的异常(不可分配给 RuntimeException 或 Error 的 Throwable),且该异常不可分配给该方法(在代理实例上调用该方法,并将其指派到调用处理程序)的 throws 子句中声明的任何异常类,则由代理实例上的方法调用抛出此异常。
UndeclaredThrowableException 实例包含由调用处理程序抛出的经过检查的未声明异常,而且可以使用 getUndeclaredThrowable() 方法获取。UndeclaredThrowableException 扩展了 RuntimeException,因此它是一个包装已检查异常的未经检查的异常。
从版本 1.4 开始,此异常已经更新,符合常用的异常链机制。“由调用处理程序抛出的经过检查的未声明异常”可以在构造的时候提供,并且可以通过 getUndeclaredThrowable() 方法访问,这类对象目前被认为是导致异常的原因,可以通过 Throwable.getCause() 方法以及前面提到的“遗留方法”访问它。
这是中文的API,有点拗口,没看懂,所以再看看英文的
Thrown by a method invocation on a proxy instance if its invocation handler’s invoke method throws a checked exception (a Throwable that is not assignable to RuntimeException or Error) that is not assignable to any of the exception types declared in the throws clause of the method that was invoked on the proxy instance and dispatched to the invocation handler.
An UndeclaredThrowableException instance contains the undeclared checked exception that was thrown by the invocation handler, and it can be retrieved with the getUndeclaredThrowable() method. UndeclaredThrowableException extends RuntimeException, so it is an unchecked exception that wraps a checked exception.
As of release 1.4, this exception has been retrofitted to conform to the general purpose exception-chaining mechanism. The “undeclared checked exception that was thrown by the invocation handler” that may be provided at construction time and accessed via the getUndeclaredThrowable() method is now known as the cause, and may be accessed via the Throwable.getCause() method, as well as the aforementioned “legacy method.”
说明
详细说明
这下终于看明白了,简单来说就是代理实例调用invocationhandler的invoke方法时,抛出检查型异常
这个检查型异常不属于runtimeexception和error,也没有在throws中定义,所以归到Throwable,这也是UndeclaredThrowableException中的undeclared和throwable的由来。UndeclaredThrowableExcepton是个非检查型异常,但是它包装了这个检查型异常,通过getUndeclaredThrowable()可以获取检查型异常
出现此异常的程序
AService调用dubbo方法时出现的这个错误,AService被代理了,AService的代理实例AServiceImpl$$EnhancerBySpringCGLIB$$5ace966b
中invocationhandler的invoke方法,调用dubbo服务,抛出检查型异常,这个检查型异常在AService中没有声明,undeclaredThrowableExcption就包装了这个检查型异常,从而最终抛出的是undeclaredThrowableExcption
异常栈信息
Caused by: java.lang.reflect.UndeclaredThrowableException
at com.AServiceImpl$$EnhancerBySpringCGLIB$$5ace966b.methodA(<generated>)
org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
... 1 more
Caused by: com.custom.CustomCheckedException: 程序错误
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:64)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
解决
弄明白了undeclaredthrowableexception的含义,就可以下手改程序了。既然出现了异常,就得记下异常信息,由于原始异常在undeclaredthrowableexception中,所以使用getCause()或getUndeclaredThrowable()方法获取原始异常,然后记录在log中
class AService{
methodA(){
try{
dubboService.method();
}catch(UndeclaredThrowableException excep){
Throwable t = excep.getCause();
if(t!=null){
//log t.getMessage()
}
}
}
}
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/20268.html