国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - jdk中動態代理異常處理分析:UndeclaredThrowableException

jdk中動態代理異常處理分析:UndeclaredThrowableException

2021-04-24 10:28hebaodan Java教程

最近在工作中遇到了報UndeclaredThrowableException的錯誤,通過查找相關的資料,終于解決了,所以這篇文章主要給大家介紹了關于jdk中動態代理異常處理分析:UndeclaredThrowableException的相關資料,需要的朋友可以參考下

背景

在rpc接口調用場景或者使用動態代理的場景中,偶爾會出現undeclaredthrowableexception,又或者在使用反射的場景中,出現invocationtargetexception,這都與我們所期望的異常不一致,且將真實的異常信息隱藏在更深一層的堆棧中。本文將重點分析下undeclaredthrowableexception

先給結論

使用jdk動態代理接口時,若方法執行過程中拋出了受檢異常但方法簽名又沒有聲明該異常時則會被代理類包裝成undeclaredthrowableexception拋出。

問題還原

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 接口定義
public interface iservice {
 void foo() throws sqlexception;
}
public class serviceimpl implements iservice{
 @override
 public void foo() throws sqlexception {
  throw new sqlexception("i test throw an checked exception");
 }
}
// 動態代理
public class iserviceproxy implements invocationhandler {
 private object target;
 
 iserviceproxy(object target){
  this.target = target;
 }
 
 @override
 public object invoke(object proxy, method method, object[] args) throws 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(), new iserviceproxy(service));
  try {
   serviceproxy.foo();
  } catch (exception e){
   e.printstacktrace();
  }
 }
}

運行上面的maintest,得到的異常堆棧為

?
1
2
3
4
5
6
7
8
9
10
11
12
13
java.lang.reflect.undeclaredthrowableexception
 at com.sun.proxy.$proxy0.foo(unknown source)
 at com.learn.reflect.maintest.main(maintest.java:16)
caused by: java.lang.reflect.invocationtargetexception
 at sun.reflect.nativemethodaccessorimpl.invoke0(native method)
 at sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl.java:62)
 at sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:43)
 at java.lang.reflect.method.invoke(method.java:498)
 at com.learn.reflect.iserviceproxy.invoke(iserviceproxy.java:19)
 ... 2 more
caused by: java.sql.sqlexception: i test throw an checked exception
 at com.learn.reflect.serviceimpl.foo(serviceimpl.java:11)
 ... 7 more

而我們期望的是

?
1
2
3
java.sql.sqlexception: i test throw an checked exception
 at com.learn.reflect.serviceimpl.foo(serviceimpl.java:11)
 ...

原因分析

在上述問題還原中,真實的sqlexception被包裝了兩層,先被invocationtargetexception包裝,再被undeclaredthrowableexception包裝。 其中,invocationtargetexception為受檢異常,undeclaredthrowableexception為運行時異常。 為何會被包裝呢,還要從動態代理的生成的代理類說起。

jdk動態代理會在運行時生成委托接口的具體實現類,我們通過proxygenerator手動生成下class文件,再利用idea解析class文件得到具體代理類: 截取部分:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public final class iserviceproxy$1 extends proxy implements iservice {
 private static method m1;
 private static method m2;
 private static method m3;
 private static method m0;
 
 public iserviceproxy$1(invocationhandler var1) throws {
  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) {
   throw new undeclaredthrowableexception(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", new class[0]);
   m3 = class.forname("com.learn.reflect.iservice").getmethod("foo", new class[0]);
   m0 = class.forname("java.lang.object").getmethod("hashcode", new class[0]);
  } catch (nosuchmethodexception var2) {
   throw new nosuchmethoderror(var2.getmessage());
  } catch (classnotfoundexception var3) {
   throw new noclassdeffounderror(var3.getmessage());
  }
 }
}

在調用“委托類”的foo方法時,實際上調用的代理類iserviceproxy$1的foo方法,而代理類主要邏輯是調用invocationhandler的invoke方法。 異常處理的邏輯是,對runtimeexception、接口已聲明的異常、error直接拋出,其他異常被包裝成undeclaredthrowableexception拋出。 到這里,或許你已經get了,或許你有疑問,在接口實現中的確是throw new sqlexception,為什么還會被包裝呢? 再來看iserviceproxy的invoke方法,它就是直接通過反射執行目標方法,問題就在這里了。 method.invoke(object obj, object... args)方法聲明中已解釋到,若目標方法拋出了異常,會被包裝成invocationtargetexception。(具體可查看javadoc)

所以,串起來總結就是: 具體方法實現中拋出sqlexception被反射包裝為會被包裝成invocationtargetexception,這是個受檢異常,而代理類在處理異常時發現該異常在接口中沒有聲明,所以包裝為undeclaredthrowableexception。

解決方法

在實現invocationhandler的invoke方法體中,對method.invoke(target, args);調用進行try catch,重新 throw invocationtargetexception的cause。即:

?
1
2
3
4
5
6
7
8
@override
 public object invoke(object proxy, method method, object[] args) throws throwable {
  try {
   return method.invoke(target, args);
  } catch (invocationtargetexception e){
   throw e.getcause();
  }
 }

題外話

為什么代理類中對未聲明的受檢異常轉為undeclaredthrowableexception? 因為java繼承原則:即子類覆蓋父類或實現父接口的方法時,拋出的異常必須在原方法支持的異常列表之內。 代理類實現了父接口或覆蓋父類方法

參考

https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html#icomments

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://my.oschina.net/hebaodan/blog/1584134

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产精品一区二区三区免费 | a国产在线观看 | 自拍偷拍视频网站 | 中文字幕 国产精品 | 一区二区三区在线免费播放 | 精品在线视频一区 | 欧美精品网 | 97精品超碰一区二区三区 | 狠狠色综合网站久久久久久久 | 亚洲精品片| 精品一区二区三区免费视频 | 亚洲精品国产乱码在线看蜜月 | 99国产视频 | 国产精品亚洲精品 | 色婷婷一二三 | 一级全黄性色生活片 | 久久黄色网 | 欧洲美女性开放视频 | 成人免费视频视频在线观看 免费 | 日韩精品一区二区三区中文字幕 | 中文字幕在线观看不卡视频 | 黄色电影免费在线观看 | 久久精品中文字幕 | 欧美一区二区三区在线看 | 韩国av一区二区 | 国产精品成人3p一区二区三区 | www.欧美亚洲 | 日韩高清在线一区二区三区 | 免费高清黄色 | 国产精品久久久久久亚洲影视 | 亚洲国产欧美一区二区三区丁香婷 | 一区二区日韩 | 亚洲大片av | 91视频进入 | 午夜爱爱毛片xxxx视频免费看 | 中文成人在线 | 亚洲国产精品网站 | 日本电影一区 | 国产美女一区二区三区 | 亚洲精品一区二区三区在线观看 | 成人精品一区二区三区视频播放 |