Saya mendapatkan NoSuchMethodError
kesalahan saat menjalankan program Java saya. Apa yang salah dan bagaimana cara memperbaikinya?
Saya mendapatkan NoSuchMethodError
kesalahan saat menjalankan program Java saya. Apa yang salah dan bagaimana cara memperbaikinya?
Jawaban:
Tanpa informasi lebih lanjut, sulit untuk menentukan masalah, tetapi akar masalahnya adalah bahwa Anda kemungkinan besar telah mengkompilasi kelas terhadap versi berbeda dari kelas yang tidak memiliki metode, daripada yang Anda gunakan saat menjalankannya.
Lihat jejak tumpukan ... Jika pengecualian muncul saat memanggil metode pada objek di pustaka, Anda kemungkinan besar menggunakan versi pustaka yang terpisah saat menyusun dan menjalankan. Pastikan Anda memiliki versi yang tepat di kedua tempat.
Jika pengecualian muncul saat memanggil metode pada objek yang dipakai oleh kelas yang Anda buat, maka proses build Anda tampaknya salah. Pastikan file kelas yang Anda jalankan benar-benar diperbarui ketika Anda kompilasi.
Caused by
di tumpukan jejak untuk menemukan kelas / jar pelakunya
Saya mengalami masalah Anda, dan ini adalah bagaimana saya memperbaikinya. Langkah-langkah berikut adalah cara kerja untuk menambahkan perpustakaan. Saya telah melakukan dua langkah pertama dengan benar, tetapi saya belum melakukan yang terakhir dengan menyeret file ".jar" langsung dari sistem file ke folder "lib" pada proyek gerhana saya. Selain itu, saya harus menghapus versi pustaka sebelumnya dari folder build dan folder "lib".
Perhatikan bahwa dalam kasus refleksi, Anda mendapatkan NoSuchMethodException
, sedangkan dengan kode non-reflektif, Anda dapatkan NoSuchMethodError
. Saya cenderung pergi mencari di tempat yang sangat berbeda ketika berhadapan dengan satu lawan yang lain.
Jika Anda memiliki akses untuk mengubah parameter JVM, menambahkan output verbose akan memungkinkan Anda untuk melihat kelas apa yang sedang diambil dari file JAR mana.
java -verbose:class <other args>
Ketika program Anda dijalankan, JVM harus membuang ke informasi standar seperti:
...
[Loaded junit.framework.Assert dari file: / C: /Program%20Files/junit3.8.2/junit.jar]
...
Ini biasanya disebabkan ketika menggunakan sistem build seperti Apache Ant yang hanya mengkompilasi file java ketika file java lebih baru daripada file kelas. Jika metode perubahan tanda tangan dan kelas menggunakan versi lama hal-hal yang tidak dapat dikompilasi dengan benar. Perbaikan yang biasa adalah melakukan pembangunan kembali penuh (biasanya "semut bersih" lalu "semut").
Kadang-kadang ini juga bisa disebabkan ketika kompilasi terhadap satu versi perpustakaan tetapi berjalan melawan versi yang berbeda.
Jika menggunakan Maven atau kerangka kerja lain, dan Anda mendapatkan kesalahan ini hampir secara acak, coba instal bersih seperti ...
clean install
Ini sangat mungkin bekerja jika Anda menulis objek dan Anda tahu itu memiliki metode. Bekerja untukku.
Ini juga bisa menjadi hasil dari menggunakan refleksi. Jika Anda memiliki kode yang mencerminkan kelas dan mengekstrak metode dengan nama (misalnya: dengan Class.getDeclaredMethod("someMethodName", .....)
) maka setiap kali nama metode itu berubah, seperti saat refactor, Anda harus ingat untuk memperbarui parameter ke metode refleksi untuk mencocokkan dengan tanda tangan metode baru, atau getDeclaredMethod
panggilan akan melempar a NoSuchMethodException
.
Jika ini alasannya, maka jejak tumpukan harus menunjukkan titik bahwa metode refleksi dipanggil, dan Anda hanya perlu memperbarui parameter agar sesuai dengan tanda tangan metode yang sebenarnya.
Dalam pengalaman saya, ini muncul sesekali ketika unit menguji metode / bidang pribadi, dan menggunakan TestUtilities
kelas untuk mengekstrak bidang untuk verifikasi pengujian. (Umumnya dengan kode lawas yang tidak dirancang dengan pengujian unit dalam pikiran.)
Jika Anda menulis aplikasi web, pastikan bahwa Anda tidak memiliki versi yang bertentangan dari sebuah toples di direktori global library Anda dan juga di aplikasi Anda. Anda mungkin belum tentu tahu stoples mana yang sedang digunakan oleh classloader.
misalnya
Masalah-masalah ini disebabkan oleh penggunaan objek yang sama di dua kelas yang sama. Objek yang digunakan tidak mengandung metode baru telah ditambahkan yang berisi kelas objek baru.
ex:
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$
Masalah-masalah ini disebabkan oleh 02 kelas yang sama secara bersamaan (1 dalam src, 1 dalam file jar di sini adalah gateway.jar)
Saya baru saja menyelesaikan kesalahan ini dengan memulai ulang Eclipse saya dan menjalankan applcation. Alasan untuk kasus saya mungkin karena saya mengganti file sumber saya tanpa menutup proyek atau Eclipse saya. Yang menyebabkan versi berbeda dari kelas yang saya gunakan.
Coba dengan cara ini: hapus semua file .class di bawah direktori proyek Anda (dan, tentu saja, semua subdirektori). Membangun kembali.
Terkadang mvn clean
(jika Anda menggunakan maven) tidak membersihkan file .class yang dibuat secara manual oleh javac
. Dan file-file lama berisi tanda tangan lama, mengarah ke NoSuchMethodError
.
Hanya menambah jawaban yang ada. Saya menghadapi masalah ini dengan kucing jantan dalam gerhana. Saya telah mengubah satu kelas dan melakukan langkah-langkah berikut,
Membersihkan dan membangun proyek di eclpise
bersihkan instalasi
Namun saya masih menghadapi kesalahan yang sama. Kemudian saya membersihkan tomcat, membersihkan direktori kerja tomcat dan me-restart server dan masalah saya hilang. Semoga ini bisa membantu seseorang
Untuk menjawab pertanyaan awal. Menurut java docs di sini :
"NoSuchMethodError" Dilemparkan jika aplikasi mencoba memanggil metode kelas tertentu (baik statis atau instance), dan kelas itu tidak lagi memiliki definisi metode itu.
Biasanya, kesalahan ini ditangkap oleh kompiler; kesalahan ini hanya dapat terjadi pada saat run time jika definisi kelas telah berubah secara tidak kompatibel.
Saya memperbaiki masalah ini di Eclipse dengan mengganti nama file tes Junit.
Di ruang kerja Eclipse saya, saya memiliki proyek App dan proyek Uji.
Proyek Uji memiliki proyek Aplikasi sebagai proyek yang diperlukan di jalur build.
Mulai mendapatkan NoSuchMethodError.
Kemudian saya menyadari bahwa kelas dalam proyek Uji memiliki nama yang sama dengan kelas dalam proyek Aplikasi.
App/
src/
com.example/
Projection.java
Test/
src/
com.example/
Projection.java
Setelah mengganti nama Tes ke nama yang benar "ProjectionTest.java" pengecualian hilang.
Saya memiliki kesalahan yang sama:
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)
Untuk mengatasinya saya memeriksa, pertama-tama, Diagram Modul Ketergantungan ( click in your POM the combination -> Ctrl+Alt+Shift+U
atau right click in your POM -> Maven -> Show dependencies
) untuk memahami di mana tepatnya konflik antara perpustakaan (Intelij IDEA). Dalam kasus khusus saya, saya memiliki versi dependensi Jackson yang berbeda.
1) Jadi, saya menambahkan secara langsung di POM proyek saya secara eksplisit versi tertinggi - 2.8.7 dari keduanya.
Di properti:
<jackson.version>2.8.7</jackson.version>
Dan sebagai ketergantungan:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
2) Tetapi juga bisa diselesaikan menggunakan Ketergantungan Pengecualian .
Dengan prinsip yang sama seperti di bawah ini dalam contoh:
<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>
Ketergantungan dengan versi yang tidak diinginkan akan dikeluarkan dari proyek Anda.
Dalam kasus saya, saya memiliki proyek multi-modul dan skenario seperti com.xyz.TestClass
dalam modul A
dan juga dalam modul B
dan modul A
tergantung pada modul B
. Jadi saat membuat toples perakitan saya pikir hanya satu versi kelas yang dipertahankan jika itu tidak memiliki metode yang dipanggil maka saya dapatkanNoSuchMethodError
pengecualian runtime, tetapi kompilasi baik-baik saja.
Di atas jawaban menjelaskan dengan sangat baik .. hanya untuk menambahkan satu hal Jika Anda menggunakan menggunakan gerhana gunakan ctrl + shift + T dan masukkan struktur paket kelas (misalnya: gateway.smpp.PDUEventListener), Anda akan menemukan semua guci / proyek di mana ia hadir . Hapus guci yang tidak perlu dari classpath atau tambahkan di atas di jalur kelas. Sekarang akan mengambil yang benar.
Saya mengalami masalah serupa.
Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I
Akhirnya saya mengidentifikasi akar penyebabnya adalah mengubah tipe data variabel.
Employee.java
-> Berisi variabel ( EmpId
) yang Tipe datanya telah diubah dari int
menjadi String
.ReportGeneration.java
-> Mengambil nilai menggunakan pengambil getEmpId()
,.Kita seharusnya menyatukan kembali toples dengan memasukkan hanya kelas yang dimodifikasi. Karena tidak ada perubahan pada ReportGeneration.java
saya hanya termasuk file Employee.class
in Jar. Saya harus memasukkan ReportGeneration.class
file ke dalam toples untuk menyelesaikan masalah.
Saya memiliki masalah yang sama. Ini juga disebabkan ketika ada ambiguitas di kelas. Program saya mencoba memanggil metode yang ada di dua file JAR yang ada di lokasi / jalur kelas yang sama. Hapus satu file JAR atau jalankan kode Anda sehingga hanya satu file JAR yang digunakan. Pastikan Anda tidak menggunakan JAR yang sama atau versi yang berbeda dari JAR yang sama yang berisi kelas yang sama.
DISP_E_EXCEPTION [step] [] [Z-JAVA-105 Java pengecualian java.lang.NoSuchMethodError (com.example.yourmethod)]
Sebagian besar java.lang.NoSuchMethodError tertangkap menjadi kompiler tetapi kadang-kadang dapat terjadi saat runtime. Jika kesalahan ini terjadi saat runtime maka satu-satunya alasan bisa jadi adalah perubahan dalam struktur kelas yang membuatnya tidak kompatibel.
Penjelasan Terbaik: https://www.journaldev.com/14538/java-lang-nosuchmethoderror
Saya juga mengalami kesalahan ini.
Masalah saya adalah saya telah mengubah tanda tangan metode, seperti
void invest(Currency money){...}
ke
void invest(Euro money){...}
Metode ini dipanggil dari konteks yang mirip dengan
public static void main(String args[]) {
Bank myBank = new Bank();
Euro capital = new Euro();
myBank.invest(capital);
}
Kompilator diam sehubungan dengan peringatan / kesalahan, karena modal adalah Mata Uang dan juga Euro.
Masalahnya muncul karena fakta bahwa saya hanya mengkompilasi kelas di mana metode tersebut didefinisikan - Bank, tetapi bukan kelas dari mana metode ini dipanggil, yang berisi metode main ().
Masalah ini bukan sesuatu yang mungkin Anda temui terlalu sering, karena paling sering proyek dibangun kembali secara manual atau tindakan Build dipicu secara otomatis, alih-alih hanya mengkompilasi satu kelas yang dimodifikasi.
Usecase saya adalah bahwa saya membuat file .jar yang akan digunakan sebagai perbaikan terbaru, yang tidak mengandung App.class karena ini tidak dimodifikasi. Masuk akal bagi saya untuk tidak memasukkannya karena saya mempertahankan kelas dasar argumen awal melalui warisan.
Masalahnya adalah, ketika Anda mengkompilasi kelas, bytecode yang dihasilkan agak statis , dengan kata lain, itu adalah referensi yang sulit .
Bytecode asli yang dibongkar (dibuat dengan alat javap) terlihat seperti ini:
#7 = Methodref #2.#22 // Bank.invest:(LCurrency;)V
Setelah ClassLoader memuat Bank.class yang baru dikompilasi, itu tidak akan menemukan metode seperti itu, tampaknya seolah-olah itu dihapus dan tidak diubah, dengan demikian kesalahan bernama.
Semoga ini membantu.
Saya memiliki masalah yang sama dengan Proyek Gradle saya menggunakan Intelij. Saya menyelesaikannya dengan menghapus paket .gradle (lihat tangkapan layar di bawah) dan membangun kembali Proyek. Paket .gradle
NoSuchMethodError: Saya telah menghabiskan beberapa jam untuk memperbaiki masalah ini, akhirnya memperbaikinya hanya dengan mengubah nama nama paket, membersihkan dan membangun ... Coba bersihkan bangunan terlebih dahulu jika tidak berfungsi coba ganti nama nama kelas atau nama paket dan bangun bersih .. .itu harus diperbaiki. Semoga berhasil.
Jika nama file Anda berbeda dari nama kelas yang berisi metode utama maka kemungkinan kesalahan ini dapat terjadi.