фон
В сценариях призывных к интерфейсу RPC или с использованием динамических сценариев прокси -сервера иногда встречается неэкладовое, или в сценарии отражения возникает upocationTargetException, которые не соответствуют исключению, которые мы ожидаем, и реальная информация о исключении скрыта в более глубоком стеке. Эта статья будет сосредоточена на анализе UndeclaredThorwableException
Сначала сделать вывод
При использовании интерфейса динамического прокси -сервера JDK, если обнаруженное исключение брошено во время выполнения метода, но подпись метода не объявляет исключение, оно будет завершено в класс прокси как неэклярированное разложение.
Восстановите проблему
// Определение интерфейса публичное интерфейс iservice {void foo () throws sqlexception;} открытый класс ServiceImpl реализует iservice {@Override public void foo () Throws Sqlexception {Throw New SQLexception («Я тестируйте проверенное исключение»); }} // Динамический прокси -прокси -класс IserviceProxy реализует vlocationHandler {частное объект Target; IServiceProxy (объект цели) {this.Target = target; } @Override public Object invoke (Object Proxy, Method Method, Object [] args) бросает Throwable {return Method.invoke (Target, args); }} public Class maintest {public static void main (string [] args) {iservice service = new serviceImpl (); IService serviceProxy = (iService) proxy.newProxyInstance (service.getClass (). GetClassLoader (), service.getClass (). GetInterfaces (), новый iServiceProxy (Service)); try {serviceproxy.foo (); } catch (Exception e) {e.printstackTrace (); }}}Запустите подход выше, и стек исключений
java.lang.reflect.undeclaredThorwableException at com.sun.proxy. $ proxy0.foo (неизвестный источник) на com.learn.reflect.maintest.main (maintest.java:16), вызванная: java.lang.reflect.invocationTargetExcept Метод) в sun.reflect.nativemethodaccessorimpl.invoke (nativemethodaccessorimpl.java:62) на sun.reflect.delegatingmethodaccessorimpl.invoke (делегирование methodaccessorimpl.java:43) на java.lang.reflect.method.invoke. com.learn.reflect.iserviceproxy.invoke (iServiceProxy.java:19) ... 2 MoreCaUsed by: java.sql.sqlexpect
Что мы ожидаем
java.sql.sqlexception: i test test test зарегистрированное исключение в com.learn.reflect.serviceimpl.foo (serviceImpl.java:11) ...
Причина анализа
В приведенной выше восстановлении задачи реальное SQLEXCEPTION обернуто в два слоя, сначала завернутые в INPOCECETARGETEXCECTION, а затем обернуто UndEclaredThableException. Среди них InvocationTargetException является обнаруженным исключением, а UndeclaredThableException - это исключение времени выполнения. Почему это обернуто? Это также начинается с прокси -класса, сгенерированного Dynamic Proxy.
Dynamic Dynamic Proxy будет генерировать конкретный класс реализации интерфейса делегата во время выполнения. Мы вручную генерируем файл класса через проксигенератор, а затем используем идею для анализа файла класса для получения конкретного класса прокси: перехватить часть:
публичный окончательный класс iServiceProxy $ 1 расширяет прокси -реализацию Iservice {частный статический метод M1; частный статический метод M2; частный статический метод M3; частный статический метод M0; public iServiceProxy $ 1 (vococationHandler var1) бросает {super (var1); } public final void foo () throws sqlexception {try {super.h.invoke (this, m3, (object []) null); } catch (runtimeexception | sqlexception | error var2) {throw var2; } catch (throwable var3) {бросить новый UndEclaredTharwableException (var3); }} static {try {m1 = class.forname ("java.lang.object"). getmethod ("equals", new class [] {class.forname ("java.lang.object")}); m2 = class.forname ("java.lang.object"). getMethod ("toString", новый класс [0]); m3 = class.forname ("com.learn.reflect.iservice"). getMethod ("foo", новый класс [0]); m0 = class.forname ("java.lang.object"). getmethod ("hashcode", новый класс [0]); } catch (nosuchmethodexception var2) {бросить новый nosuchmethoderror (var2.getmessage ()); } catch (classnotfoundexception var3) {бросить новый noclassdeffounderror (var3.getmessage ()); }}}При вызове метода Foo «класса делегата», метод FOO класса Proxy IserviceProxy $ 1 фактически вызывается, и основная логика класса прокси - это вызвать метод Invoke of vocationHandler. Логика обработки исключений заключается в том, чтобы напрямую бросить runtimeexception, исключение, объявленное интерфейсом, и ошибка выброшена, а другие исключения обернуты как UndeclaredThableException. На данный момент, может быть, у вас уже есть это, может быть, у вас есть вопрос, в реализации интерфейса это действительно новое SQLEXCEPTION, почему оно все еще обернуто? Давайте посмотрим на метод IserviceProxy. Он непосредственно выполняет целевой метод посредством отражения. Это проблема. Method.invoke (объект obj, объект ... args) Объявление метода было объяснено, что если целевой метод бросает исключение, он будет завершен как vocationTargetException. (Для получения подробной информации, пожалуйста, проверьте Javadoc)
Следовательно, краткое изложение: в конкретной реализации метода SQLEXCEPTION выбрасывается и отражается и обернута как InvocationTargetException. Это проверенное исключение. Когда класс прокси обрабатывает исключение, он обнаруживает, что исключение не объявлено в интерфейсе, поэтому оно упаковано как неэкладовое.
Решение
В теле метода Invoke, который реализует vocationHandler, попробуйте поймать метод. INVOKE (Target, Args); Позвоните и бросьте причину vocationTargetException. Прямо сейчас:
@Override public Object invoke (Proxy Object, метод метода, объект [] args) бросает Throwable {try {return Method.invoke (target, args); } catch (vococationTargetException e) {throw e.getCause (); }}Не по теме
Почему неопровержимое исключение в классе Proxy превращается в неэкладовое обследование? Из -за принципа наследования Java: когда подкласс переопределяет родительский класс или метод, который реализует родительский интерфейс, исключение брошенных должно быть в списке исключений, поддерживаемое исходным методом. Класс прокси реализует родительский интерфейс или перезаписывает метод родительского класса
обратиться к
https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html#icomments
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.