ฉันพบ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) ที่มีข้อมูลประเภทมีการเปลี่ยนแปลงจากการintStringReportGeneration.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 ควรได้รับการแก้ไข โชคดี.
หากชื่อไฟล์ของคุณแตกต่างจากชื่อคลาสที่มีวิธีการหลักอาจเป็นไปได้ว่าข้อผิดพลาดนี้อาจเกิดขึ้น