สิ่งที่อาจทำให้เกิด java.lang.reflect.InvocationTargetException?


313

ฉันพยายามทำความเข้าใจและอ่านสิ่งที่อาจทำให้เกิด แต่ฉันไม่สามารถทำได้:

ฉันมีสิ่งนี้ในรหัสของฉัน:

 try{
 ..
 m.invoke(testObject);
 ..
 } catch(AssertionError e){
 ...
 } catch(Exception e){
 ..
 }

สิ่งนั้นคือเมื่อมันพยายามเรียกใช้วิธีการบางอย่างมันจะโยน InvocationTargetExceptionแทนที่จะเป็นข้อยกเว้นที่คาดหวังอื่น ๆ (โดยเฉพาะArrayIndexOutOfBoundsException) ในฐานะที่เป็นจริงผมรู้ว่าสิ่งที่วิธีการที่จะเรียกผมเดินตรงไปยังรหัสวิธีนี้และเพิ่มลองจับบล็อกบรรทัดที่คิดว่าจะโยน ArrayIndexOutOfBoundsExceptionและมันจริงๆโยนArrayIndexOutOfBoundsExceptionตามที่คาดไว้ แต่เมื่อขึ้นไปก็เปลี่ยนไปInvocationTargetExceptionและในรหัสข้างต้นcatch(Exception e) e คือInvocationTargetExceptionและไม่ArrayIndexOutOfBoundsException เป็นไปตามที่คาดไว้

สิ่งใดที่อาจทำให้เกิดพฤติกรรมดังกล่าวหรือฉันจะตรวจสอบสิ่งนั้นได้อย่างไร

คำตอบ:


333

คุณได้เพิ่มระดับพิเศษของนามธรรมโดยเรียกวิธีการที่มีการสะท้อน ชั้นสะท้อน wraps ข้อยกเว้นใด ๆ ในInvocationTargetExceptionซึ่งช่วยให้คุณบอกความแตกต่างระหว่างการยกเว้นจริงที่เกิดจากความล้มเหลวในการเรียกสะท้อนที่ (อาจจะรายการอาร์กิวเมนต์ของคุณไม่ถูกต้องตัวอย่างเช่น) และความล้มเหลวภายในวิธีการที่เรียกว่า

เพียงแกะสาเหตุภายในInvocationTargetExceptionและคุณจะไปถึงต้นเหตุ


4
@ user550413: โดยการแกะข้อยกเว้นและตรวจสอบสิ่งนั้นแน่นอน คุณสามารถโยนมันด้วยตัวคุณเองและจับมันถ้าคุณต้องการ
Jon Skeet

157
สำหรับใครที่สงสัยเกี่ยวกับการ "แกะสาเหตุภายในInvocationTargetException" ฉันเพิ่งค้นพบว่าถ้าคุณได้รับมันพิมพ์โดยใช้exception.printStackTrace()คุณเพียงดูที่ส่วน "สาเหตุโดย:" แทนส่วนครึ่ง / ปกติด้านบน
มกราคม

31
หากต้องการเพิ่มคำอธิบายเกี่ยวกับ "การคลายออก" คุณยังสามารถตรวจจับข้อยกเว้นและใช้เมธอด getCause () บนซึ่งสามารถนำมาใช้ใหม่ได้หากต้องการ สิ่งที่ชอบtry {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }หรือ...catch... { throw ex.getCause() }
jcadcell

4
+1 @Hanan สำหรับ you just look at the "Caused By:" section instead of the top half/normal section
GingerHead

1
@DheraajBhaskar อย่าแก้ไขคำตอบของคนอื่นราวกับว่าพวกเขาเป็นของคุณเองและอย่าใช้การจัดรูปแบบคำพูดสำหรับข้อความที่ไม่ได้ยกมา การแก้ไขนั้นควรถูกโพสต์เป็นความคิดเห็น
มาร์ควิสแห่ง Lorne

51

ข้อยกเว้นจะถูกโยนถ้า

InvocationTargetException - ถ้าวิธีการพื้นฐานส่งข้อยกเว้น

ดังนั้นถ้าวิธีการที่ได้รับการเรียกด้วยการสะท้อน API, พ่นยกเว้น (ยกเว้นรันไทม์ตัวอย่าง) สะท้อน API InvocationTargetExceptionจะห่อยกเว้นเข้าไปในนั้น


คำอธิบายที่ดี!
gaurav

จะเกิดอะไรขึ้นถ้าฉันคาดว่าวิธีการพื้นฐานจะใช้การยกเว้น ฉันควรจะได้รับการยกเว้นนี้
jDub9


21

จาก Javadoc ของ Method.invoke ()

พ่น: InvocationTargetException - ถ้าวิธีการพื้นฐานส่งข้อยกเว้น

ข้อยกเว้นนี้จะถูกโยนถ้าวิธีการที่เรียกว่าโยนข้อยกเว้น


ลองจินตนาการว่าฉันมีตัวอย่างของการjava.lang.reflect.Proxyเพิ่มวัตถุที่ถูกห่อหุ้ม แต่ละคนProxyได้อย่างสง่างามจัดการข้อยกเว้นเฉพาะเจาะจง (อาจจะโยนวัตถุห่อ) InvocationHandlerโดยใช้ของตัวเอง สำหรับข้อยกเว้นในการกระเพื่อมผ่านน้ำตกนี้จนกว่าจะถึงตัวจัดการ / พร็อกซีการร้องขอที่ถูกต้องในแต่ละครั้งInvocationHandlerฉันจะตรวจจับInvocationTargetExceptionแกะห่อตรวจสอบว่าข้อยกเว้นที่ห่อไว้นั้นเป็นinstanceofข้อยกเว้นที่จะจัดการโดยนี้InvocationHandlerหรือไม่ ถ้าไม่ใช่instanceof, ฉันจะโยนข้อยกเว้นที่ยังไม่ได้เปิด ... ใช่ไหม?
Abdull

ฉันมักจะโยนข้อยกเว้นที่ยังไม่ได้เปิด
Peter Lawrey

9

ที่อาจจะมีการห่อของคุณInvocationTargetException ArrayIndexOutOfBoundsExceptionไม่มีการบอกล่วงหน้าเมื่อใช้การสะท้อนสิ่งที่วิธีการนั้นสามารถทำได้ - ดังนั้นแทนที่จะใช้throws Exceptionวิธีการข้อยกเว้นทั้งหมดจะถูกจับและรวมเข้าด้วยInvocationTargetExceptionกัน


ขอบคุณ แต่นั่นฉันจะแตกต่างกันอย่างไร (AssertionError e) และ (Exception e) เป็นตัวอย่าง? ถ้าฉันได้รับ InvocationTargetException เสมอก่อนที่จะแยกสาเหตุที่ฉันจะแตกต่างกันระหว่างข้อยกเว้นแต่ละข้อ
user550413

9

สิ่งนี้จะพิมพ์บรรทัดของรหัสที่แน่นอนในวิธีการเฉพาะซึ่งเมื่อเรียกใช้ยกข้อยกเว้น:

try {

    // try code
    ..
    m.invoke(testObject);
    ..

} catch (InvocationTargetException e) {

    // Answer:
    e.getCause().printStackTrace();
} catch (Exception e) {

    // generic exception handling
    e.printStackTrace();
}

1
ขอบคุณ; สิ่งนี้ช่วยให้ฉันตระหนักว่าปัญหาของฉันไม่ได้อยู่ในการสะท้อนตัวเอง แต่เป็นวิธีการที่เรียกใช้
Jose Gómez

3

สิ่งนี้อธิบายบางสิ่งเช่น

InvocationTargetException เป็นข้อยกเว้นที่ตรวจสอบซึ่งล้อมรอบข้อยกเว้นที่ส่งออกมาโดยเมธอดที่เรียกใช้หรือตัวสร้าง ตั้งแต่รีลีส 1.4 ข้อยกเว้นนี้ได้รับการดัดแปลงเพิ่มเติมเพื่อให้สอดคล้องกับกลไกการยกเว้นข้อผูกพันทั่วไป "ข้อยกเว้นเป้าหมาย" ที่ให้ไว้ ณ เวลาก่อสร้างและเข้าถึงผ่านเมธอด getTargetException () เป็นที่รู้จักกันในชื่อสาเหตุและอาจเข้าถึงได้ผ่านวิธี Throwable.getCause () รวมถึงวิธี "มรดกดั้งเดิม" ที่กล่าวมาข้างต้น


2

คุณสามารถเปรียบเทียบกับคลาสข้อยกเว้นเดิมโดยใช้เมธอด getCause () ดังนี้:

try{
  ...
} catch(Exception e){
   if(e.getCause().getClass().equals(AssertionError.class)){
      // handle your exception  1
   } else {
      // handle the rest of the world exception 
   }
} 

1

ฉันมีjava.lang.reflect.InvocationTargetExceptionข้อผิดพลาดจากคำสั่งที่เรียกวัตถุตัวบันทึกในภายนอกclassภายในtry/ catchบล็อกในของฉันclassบล็อกของฉัน

การก้าวผ่านโค้ดในดีบักเกอร์ Eclipse & วางเมาส์เหนือคำสั่งตัวบันทึกที่ฉันเห็นตัวบันทึกobjectคือnull(ค่าคงที่ภายนอกบางอันจำเป็นต้องมีอินสแตนซ์ที่ด้านบนสุดของฉันclass)


0

ข้อยกเว้นนี้จะถูกโยนถ้าวิธีการพื้นฐาน (วิธีการที่เรียกว่าใช้สะท้อน) โยนข้อยกเว้น

ดังนั้นหากวิธีการที่ถูกเรียกใช้โดย reflection API ส่งข้อยกเว้น (เช่นข้อยกเว้นรันไทม์), API การสะท้อนกลับจะตัดข้อยกเว้นลงใน InvocationTargetException


0

ฉันกำลังเผชิญกับปัญหาเดียวกัน ฉันใช้ e.getCause (). getCause () จากนั้นฉันก็พบว่ามันเป็นเพราะพารามิเตอร์ผิดพลาดที่ฉันส่งผ่าน มี nullPointerException ในการดึงค่าของหนึ่งในพารามิเตอร์ หวังว่านี่จะช่วยคุณได้


-2
  1. แสดงรายการไฟล์ jar ทั้งหมดจากโหมด Eclipse Navigator
  2. ตรวจสอบว่าไฟล์ jar ทั้งหมดอยู่ในโหมดไบนารี

4
คุณจะตรวจสอบว่าไฟล์ jar อยู่ในโหมดไบนารีได้อย่างไรโดยดูจากไฟล์ในนาวิเกเตอร์?
วิลเลียม

@ วิลเลียมคุณทำให้ฉันหัวเราะฮ่าฮ่าฮ่า คำตอบของผู้ชายคนนี้ควรจะลดลง
Karim Manaouil

-7

ข้อผิดพลาดหายไปหลังจากที่ฉันทำความสะอาด -> เรียกใช้ xDoclet-> เรียกใช้ xPackaging

ในพื้นที่ทำงานของฉันใน ecllipse

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.