ฉันพบNoSuchMethodError
ข้อผิดพลาดเมื่อเรียกใช้โปรแกรม Java ของฉัน เกิดอะไรขึ้นและฉันจะแก้ไขได้อย่างไร
ฉันพบNoSuchMethodError
ข้อผิดพลาดเมื่อเรียกใช้โปรแกรม Java ของฉัน เกิดอะไรขึ้นและฉันจะแก้ไขได้อย่างไร
คำตอบ:
หากไม่มีข้อมูลเพิ่มเติมเป็นการยากที่จะระบุปัญหา แต่สาเหตุที่แท้จริงคือคุณมักจะรวบรวมคลาสกับรุ่นอื่นของคลาสที่ขาดวิธีการมากกว่าที่คุณใช้เมื่อเรียกใช้
ดูที่การติดตามสแต็ก ... หากข้อยกเว้นปรากฏขึ้นเมื่อเรียกใช้เมธอดบนวัตถุในไลบรารีคุณมักจะใช้ไลบรารีเวอร์ชันแยกต่างหากเมื่อทำการคอมไพล์และรัน ตรวจสอบให้แน่ใจว่าคุณมีเวอร์ชั่นที่ถูกต้องทั้งสองแห่ง
หากข้อยกเว้นปรากฏขึ้นเมื่อเรียกใช้เมธอดบนอ็อบเจ็กต์ที่สร้างอินสแตนซ์โดยคลาสที่คุณทำกระบวนการสร้างของคุณดูเหมือนจะผิดพลาด ตรวจสอบให้แน่ใจว่าไฟล์คลาสที่คุณกำลังใช้งานจริงได้รับการอัพเดตเมื่อคุณคอมไพล์
Caused by
ส่วนสุดท้ายใน stack trace เพื่อหาคลาส / jar ผู้ร้าย
ฉันมีปัญหาของคุณและนี่คือวิธีที่ฉันจะแก้ไข ขั้นตอนต่อไปนี้เป็นวิธีการทำงานในการเพิ่มห้องสมุด ฉันทำสองขั้นตอนแรกถูกแล้ว แต่ฉันไม่ได้ทำขั้นตอนสุดท้ายด้วยการลากไฟล์ ".jar" โดยตรงจากระบบไฟล์ไปยังโฟลเดอร์ "lib" ในโครงการ eclipse ของฉัน นอกจากนี้ฉันต้องลบไลบรารีรุ่นก่อนหน้าออกจากทั้งเส้นทางการสร้างและโฟลเดอร์ "lib"
ทราบว่าในกรณีของการสะท้อนที่คุณได้รับในขณะที่มีรหัสไม่สะท้อนแสงคุณจะได้รับNoSuchMethodException
NoSuchMethodError
ฉันมักจะมองในที่ต่าง ๆ เมื่อเผชิญหน้ากับที่หนึ่งกับที่อื่น
หากคุณมีสิทธิ์เข้าถึงเพื่อเปลี่ยนพารามิเตอร์ JVM การเพิ่มเอาต์พุตแบบ verbose ควรอนุญาตให้คุณดูว่าคลาสใดที่ถูกโหลดจากไฟล์ JAR ใด
java -verbose:class <other args>
เมื่อโปรแกรมของคุณรัน JVM ควรถ่ายโอนข้อมูลออกมาตรฐานเช่น:
...
[โหลด junit.framework.Assert จากไฟล์: / C: /Program%20Files/junit3.8.2/junit.jar]
...
ซึ่งมักจะเกิดขึ้นเมื่อใช้ระบบบิลด์เช่นApache Antที่จะรวบรวมไฟล์ java เท่านั้นเมื่อไฟล์ java นั้นใหม่กว่าไฟล์คลาส หากมีการเปลี่ยนแปลงลายเซ็นวิธีการและชั้นเรียนที่ใช้สิ่งที่รุ่นเก่าอาจไม่ได้รวบรวมอย่างถูกต้อง การแก้ไขตามปกติคือทำการสร้างใหม่อย่างสมบูรณ์ (โดยปกติจะเป็น "มดสะอาด" และ "มด")
บางครั้งสิ่งนี้อาจเกิดขึ้นได้เมื่อคอมไพล์กับไลบรารีเวอร์ชันหนึ่ง แต่ทำงานกับเวอร์ชันอื่น
หากใช้Mavenหรือกรอบงานอื่นและคุณได้รับข้อผิดพลาดนี้แบบสุ่มให้ลองติดตั้งใหม่เช่น ...
clean install
สิ่งนี้มีแนวโน้มที่จะทำงานโดยเฉพาะอย่างยิ่งถ้าคุณเขียนวัตถุและคุณรู้ว่ามันมีวิธีการ ทำงานให้ฉัน
นี่อาจเป็นผลมาจากการใช้การสะท้อน หากคุณมีรหัสที่สะท้อนถึงคลาสและแยกเมธอดตามชื่อ (เช่น: ด้วยClass.getDeclaredMethod("someMethodName", .....)
) เมื่อใดก็ตามที่มีการเปลี่ยนชื่อเมธอดเช่นระหว่าง refactor คุณจะต้องจำไว้ว่าต้องอัปเดตพารามิเตอร์เป็นวิธีการสะท้อนเพื่อให้ตรงกับ ลายเซ็นวิธีการใหม่หรือการgetDeclaredMethod
โทรจะส่งNoSuchMethodException
โทรจะโยน
หากนี่คือเหตุผลการติดตามสแต็คควรแสดงจุดที่วิธีการสะท้อนถูกเรียกใช้และคุณเพียงแค่ต้องอัปเดตพารามิเตอร์เพื่อให้ตรงกับลายเซ็นของวิธีการจริง
จากประสบการณ์ของฉันสิ่งนี้เกิดขึ้นเป็นครั้งคราวเมื่อหน่วยทดสอบวิธี / ฟิลด์ส่วนตัวและใช้TestUtilities
คลาสเพื่อแยกฟิลด์สำหรับการตรวจสอบการทดสอบ (โดยทั่วไปคือรหัสดั้งเดิมที่ไม่ได้ออกแบบมาโดยคำนึงถึงการทดสอบหน่วย)
หากคุณกำลังเขียน webapp ตรวจสอบให้แน่ใจว่าคุณไม่มี jar เวอร์ชันที่ขัดแย้งกันในไดเรกทอรีไลบรารีส่วนกลางของ container และใน app ของคุณ คุณอาจไม่จำเป็นต้องทราบว่า classloader นั้นกำลังใช้ jar ใด
เช่น
ปัญหาเหล่านี้เกิดจากการใช้วัตถุเดียวกันที่สองชั้นเดียวกัน วัตถุที่ใช้ไม่ได้มีวิธีการใหม่ที่ได้รับการเพิ่มที่มีคลาสวัตถุใหม่
อดีต:
filenotnull=/DayMoreConfig.conf
16-07-2015 05:02:10:ussdgw-1: Open TCP/IP connection to SMSC: 10.149.96.66 at 2775
16-07-2015 05:02:10:ussdgw-1: Bind request: (bindreq: (pdu: 0 9 0 [1]) 900 900 GEN 52 (addrrang: 0 0 2000) )
Exception in thread "main" java.lang.NoSuchMethodError: gateway.smpp.PDUEventListener.<init>(Lgateway/smpp/USSDClient;)V
at gateway.smpp.USSDClient.bind(USSDClient.java:139)
at gateway.USSDGW.initSmppConnection(USSDGW.java:274)
at gateway.USSDGW.<init>(USSDGW.java:184)
at com.vinaphone.app.ttn.USSDDayMore.main(USSDDayMore.java:40)
-bash-3.00$
ปัญหาเหล่านี้เกิดจากคลาสที่คล้ายกัน 02 (1 ใน src, 1 ในไฟล์ jar ที่นี่คือ gateway.jar)
มันหมายถึงวิธีการที่เกี่ยวข้องไม่ได้อยู่ในชั้นเรียน:
สำหรับฉันมันเกิดขึ้นเพราะฉันเปลี่ยนประเภทอาร์กิวเมนต์ในฟังก์ชั่นจาก Object a เป็น String a ฉันสามารถแก้ไขได้ด้วยความสะอาดและสร้างอีกครั้ง
ฉันเพิ่งแก้ไขข้อผิดพลาดนี้ได้โดยการรีสตาร์ท Eclipse และเรียกใช้ applcation เหตุผลสำหรับเคสของฉันอาจเป็นเพราะฉันแทนที่ไฟล์ต้นฉบับโดยไม่ต้องปิดโปรเจ็กต์หรือ Eclipse ซึ่งทำให้ชั้นเรียนรุ่นที่แตกต่างกันที่ฉันใช้อยู่
ลองด้วยวิธีนี้: ลบไฟล์. class ทั้งหมดภายใต้ไดเรกทอรีโครงการของคุณ (และแน่นอนไดเรกทอรีย่อยทั้งหมด) สร้างใหม่
บางครั้งmvn clean
(ถ้าคุณกำลังใช้ Maven) ไม่ .class javac
สะอาดไฟล์ที่สร้างขึ้นด้วยตนเองโดย NoSuchMethodError
และไฟล์เก่าที่มีลายเซ็นเก่าที่นำไปสู่
เพียงเพิ่มคำตอบที่มีอยู่ ฉันกำลังเผชิญกับปัญหานี้กับคราวในคราส ฉันเปลี่ยนชั้นหนึ่งและทำตามขั้นตอน
ทำความสะอาดและสร้างโครงการใน eclpise
mvn ทำความสะอาดติดตั้ง
ยังฉันกำลังเผชิญข้อผิดพลาดเดียวกัน จากนั้นฉันก็ล้าง Tomcat ทำความสะอาดไดเรกทอรีการทำงาน Tomcatและรีสตาร์ทเซิร์ฟเวอร์และปัญหาของฉันหายไป หวังว่านี่จะช่วยใครซักคน
เพื่อตอบคำถามเดิม ตามเอกสาร java ที่นี่ :
"NoSuchMethodError" ส่งออกมาหากแอปพลิเคชันพยายามเรียกวิธีการที่ระบุของคลาส (แบบคงที่หรืออินสแตนซ์) และคลาสนั้นไม่มีคำจำกัดความของวิธีการนั้นอีกต่อไป
โดยปกติข้อผิดพลาดนี้จะถูกรวบรวมโดยคอมไพเลอร์; ข้อผิดพลาดนี้สามารถเกิดขึ้นได้ในขณะดำเนินการถ้าคำจำกัดความของคลาสมีการเปลี่ยนแปลงเข้ากันไม่ได้
ฉันแก้ไขปัญหานี้ใน Eclipse โดยเปลี่ยนชื่อไฟล์ทดสอบ Junit
ในพื้นที่ทำงาน Eclipse ของฉันฉันมีโครงการแอพและโครงการทดสอบ
โปรเจ็กต์ทดสอบมีโปรเจ็กต์ App เป็นโปรเจ็กต์ที่จำเป็นบนพา ธ บิลด์
เริ่มรับ NoSuchMethodError
จากนั้นฉันก็รู้ว่าชั้นเรียนในโครงการทดสอบมีชื่อเดียวกับชั้นเรียนในโครงการแอพ
App/
src/
com.example/
Projection.java
Test/
src/
com.example/
Projection.java
หลังจากเปลี่ยนชื่อการทดสอบเป็นชื่อที่ถูกต้อง "ProjectionTest.java" ข้อยกเว้นก็หายไป
ฉันมีข้อผิดพลาดเดียวกัน:
Exception in thread "main" java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonGenerator.writeStartObject(Ljava/lang/Object;)V
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:151)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3681)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3057)
ในการแก้ปัญหาฉันได้ตรวจสอบอันดับแรกคือแผนภาพการพึ่งพาโมดูล ( click in your POM the combination -> Ctrl+Alt+Shift+U
หรือright click in your POM -> Maven -> Show dependencies
) เพื่อทำความเข้าใจว่าข้อขัดแย้งระหว่างไลบรารี (Intelij IDEA) คืออะไร ในกรณีเฉพาะของฉันฉันมีรุ่นที่แตกต่างกันของการพึ่งพาแจ็กสัน
1) ดังนั้นฉันเพิ่มโดยตรงใน POM ของฉันของโครงการอย่างชัดเจนรุ่นสูงสุด - 2.8.7 ของทั้งสอง
ในคุณสมบัติ:
<jackson.version>2.8.7</jackson.version>
และเป็นที่พึ่ง:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
2) แต่ยังจะสามารถแก้ไขได้โดยใช้การพึ่งพาการยกเว้น
โดยหลักการเดียวกันกับตัวอย่างด้านล่าง:
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
การพึ่งพาเวอร์ชันที่ไม่ต้องการจะถูกแยกออกจากโครงการของคุณ
ในกรณีของฉันฉันมีโครงการหลายโมดูลและสถานการณ์เป็นเหมือนcom.xyz.TestClass
อยู่ในโมดูลA
และเช่นเดียวกับในโมดูลB
และโมดูลขึ้นอยู่กับโมดูลA
B
ดังนั้นในขณะที่สร้างขวดแอสเซมบลีฉันคิดว่าคลาสรุ่นเดียวเท่านั้นที่ถูกเก็บไว้ถ้าไม่มีวิธีการเรียกใช้แล้วฉันได้รับNoSuchMethodError
ข้อยกเว้นรันไทม์ แต่การรวบรวมทำได้ดี
ที่เกี่ยวข้อง: https://reflectoring.io/nosuchmethod/
ฉันพบปัญหาที่คล้ายกันเมื่อฉันเปลี่ยนลายเซ็นวิธีในแอปพลิเคชันของฉัน การทำความสะอาดและสร้างโครงการของฉันใหม่แก้ไข "NoSuchMethodError"
คำตอบข้างต้นอธิบายได้ดีมาก .. เพียงแค่เพิ่มสิ่งหนึ่งถ้าคุณใช้ eclipse ให้ใช้ ctrl + shift + T และใส่โครงสร้างแพ็คเกจของคลาส (เช่น: gateway.smpp.PDUEventListener) คุณจะพบขวด / โครงการทั้งหมดที่มีอยู่ . ลบ jars ที่ไม่จำเป็นออกจาก classpath หรือเพิ่มข้างบนใน class path ตอนนี้มันจะรับที่ถูกต้อง
ฉันพบปัญหาเดียวกัน
Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I
ในที่สุดฉันก็พบว่าสาเหตุที่แท้จริงคือการเปลี่ยนประเภทข้อมูลของตัวแปร
Employee.java
-> มีตัวแปร ( EmpId
) ที่มีข้อมูลประเภทมีการเปลี่ยนแปลงจากการint
String
ReportGeneration.java
-> getEmpId()
ดึงค่าใช้ทะเยอทะยานที่เราควรจะ rebundle jar โดยรวมเฉพาะคลาสที่แก้ไข เนื่องจากไม่มีการเปลี่ยนแปลงในReportGeneration.java
ฉันเป็นเพียงการรวมEmployee.class
ในไฟล์ Jar ฉันต้องรวมReportGeneration.class
ไฟล์ไว้ใน jar เพื่อแก้ไขปัญหา
ฉันมีปัญหาเดียวกัน เรื่องนี้เกิดขึ้นเมื่อมีความกำกวมในชั้นเรียน โปรแกรมของฉันพยายามเรียกใช้เมธอดที่มีอยู่ในไฟล์ JAR สองไฟล์ที่อยู่ในตำแหน่ง / พา ธ คลาสเดียวกัน ลบไฟล์ JAR หนึ่งไฟล์หรือเรียกใช้รหัสของคุณเพื่อให้ใช้ไฟล์ JAR เพียงไฟล์เดียว ตรวจสอบว่าคุณไม่ได้ใช้ JAR เดียวกันหรือ JAR รุ่นเดียวกันที่มีคลาสเดียวกัน
DISP_E_EXCEPTION [ขั้นตอน] [] [Z-JAVA-105 ข้อยกเว้น Java java.lang.NoSuchMethodError (com.example.yourmethod)]
ส่วนใหญ่ของเวลา java.lang.NoSuchMethodError นั้นถูกคอมไพเลอร์ แต่บางครั้งก็สามารถเกิดขึ้นได้ในขณะรันไทม์ หากข้อผิดพลาดนี้เกิดขึ้นที่รันไทม์เหตุผลเดียวที่สามารถเปลี่ยนแปลงได้ในโครงสร้างคลาสที่ทำให้ไม่สามารถทำงานร่วมกันได้
คำอธิบายที่ดีที่สุด: https://www.journaldev.com/14538/java-lang-nosuchmethoderror
ฉันก็พบข้อผิดพลาดนี้เช่นกัน
ปัญหาของฉันคือฉันเปลี่ยนลายเซ็นของวิธีการเช่น
void invest(Currency money){...}
เข้าไป
void invest(Euro money){...}
วิธีนี้ถูกเรียกจากบริบทที่คล้ายกับ
public static void main(String args[]) {
Bank myBank = new Bank();
Euro capital = new Euro();
myBank.invest(capital);
}
คอมไพเลอร์เงียบไปเนื่องจากคำเตือน / ข้อผิดพลาดเนื่องจากเงินทุนเป็นทั้งสกุลเงินและยูโร
ปัญหาปรากฏขึ้นเนื่องจากความจริงที่ว่าฉันรวบรวมเฉพาะคลาสที่กำหนดวิธีการ - ธนาคาร แต่ไม่ใช่คลาสที่วิธีนั้นถูกเรียกจากซึ่งมีเมธอด main ()
ปัญหานี้ไม่ใช่สิ่งที่คุณอาจพบบ่อยเกินไปเนื่องจากบ่อยครั้งที่โปรเจ็กต์ถูกสร้างใหม่ด้วยตนเองหรือการดำเนินการ Build ถูกทริกเกอร์โดยอัตโนมัติแทนที่จะรวบรวมคลาสที่แก้ไขแล้วหนึ่งคลาส
usecase ของฉันคือฉันสร้างไฟล์. jar ซึ่งจะใช้เป็นโปรแกรมแก้ไขด่วนที่ไม่มี App.class เนื่องจากไม่ได้แก้ไข มันสมเหตุสมผลสำหรับฉันที่จะไม่รวมไว้ในขณะที่ฉันเก็บการสืบทอดรางน้ำของคลาสเริ่มต้นของอาร์กิวเมนต์
สิ่งที่เป็นเมื่อคุณคอมไพล์ชั้นเรียนที่ bytecode ส่งผลให้เป็นชนิดของแบบคงที่ในคำอื่น ๆ ก็เป็นเรื่องยากที่อ้างอิง
ไบต์ที่ถูกแยกส่วนแบบดั้งเดิม (สร้างขึ้นด้วยเครื่องมือ javap) มีลักษณะดังนี้:
#7 = Methodref #2.#22 // Bank.invest:(LCurrency;)V
หลังจาก ClassLoader โหลด Bank.class ที่คอมไพล์แล้วใหม่มันจะไม่พบวิธีดังกล่าวมันจะปรากฏราวกับว่ามันถูกลบออกและไม่เปลี่ยนแปลงดังนั้นจึงเกิดข้อผิดพลาดในชื่อ
หวังว่านี่จะช่วยได้
ปัญหาในกรณีของฉันคือมีไลบรารีเดียวกันสองเวอร์ชันในพา ธ บิลด์ ไลบรารีเวอร์ชันเก่ากว่าไม่มีฟังก์ชันและใหม่กว่านั้น
ฉันมีปัญหาที่คล้ายกันกับโครงการ Gradle ของฉันโดยใช้ Intelij ฉันแก้ไขได้ด้วยการลบ. package (ดูภาพด้านล่าง) แพ็คเกจและสร้างโครงการขึ้นใหม่ .gradle Package
NoSuchMethodError: ฉันใช้เวลาสองสามชั่วโมงในการแก้ไขปัญหานี้ในที่สุดก็แก้ไขได้โดยเพียงแค่เปลี่ยนชื่อแพ็คเกจทำความสะอาดและสร้าง ... ลอง clean build ก่อนถ้าไม่ทำงานลองเปลี่ยนชื่อ class หรือชื่อ package และ clean build .. .it ควรได้รับการแก้ไข โชคดี.
หากชื่อไฟล์ของคุณแตกต่างจากชื่อคลาสที่มีวิธีการหลักอาจเป็นไปได้ว่าข้อผิดพลาดนี้อาจเกิดขึ้น