Bagaimana cara saya memperbaiki NoSuchMethodError?


178

Saya mendapatkan NoSuchMethodErrorkesalahan saat menjalankan program Java saya. Apa yang salah dan bagaimana cara memperbaikinya?


11
Di Netbeans: Klik kanan pada proyek di tab Projects, gunakan "Clean and Build". Memecahkannya untukku.
Heinzlmaen

3
Juga di Intellij Idea, membangun kembali kadang
Hawk

1
Artikel ini sangat membantu untuk masalah ini reflectoring.io/nosuchmethod
Michael Smith

Jawaban:


228

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.


3
Kami baru-baru ini menemukan penyebab salah satu dari ini dan ternyata proses build adalah meletakkan file kelas di tempat sebelum server java ditutup, dan kami menekan ini karena server java tidak memuat beberapa kelas, dan kemudian ia memuat beberapa tetapi mendapat yang baru ini, dan karena kode baru merujuk pada metode yang tidak dimiliki kelas lama ... bingo, NoSuchMethodError
vazor

"Lihat jejak tumpukan ..." - Yah, aku hampir selalu pergi dan memeriksa bagian terakhir Caused bydi tumpukan jejak untuk menemukan kelas / jar pelakunya
KrishPrabakar

108

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".

Langkah 1 - Tambahkan .jar untuk membangun jalur

masukkan deskripsi gambar di sini

Langkah 2 - Mengaitkan sumber dan javadocs (opsional)

masukkan deskripsi gambar di sini

Langkah 3 - Sebenarnya seret file .jar ke folder "lib" (bukan opsional)

masukkan deskripsi gambar di sini


75
+1 untuk "Semua orang berharap Anda tahu cara menggunakannya dan jika Anda tidak, mereka menjawab pertanyaan Anda."
Vikram

73

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.


Dengan kata lain, Anda mengatakan bahwa jika Anda menggunakan refleksi untuk mendapatkan metode di kelas dan metode itu tidak ditemukan, Anda mendapatkan NoSuchMethodException. Tetapi jika Anda berada dalam skenario ketika Anda mengkompilasi kode Anda terhadap beberapa lib dan pada server Anda memiliki lib lainnya (mungkin lebih baru mungkin lebih tua) maka Anda mendapatkan NoSuchMethodError. Koreksi saya jika saya salah.
Victor

Itu benar, @ Viktor
KrishPrabakar

51

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]

...


3
+1 Cemerlang! Saya memecahkan masalah kecil yang jahat dengan menggunakan metode ini, terima kasih. Ini adalah cara terbaik untuk mengetahui kapan kelas telah menyelinap masuk ke jalan kelas.
Duncan Jones

1
+1 Anda menyelamatkan hari saya! Itu hanya satu perpustakaan yang menyertakan kelas lama dengan nama yang sama ke sumbernya.
Andrii Nemchenko

12

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.


1
Sebenarnya, ini terasa lebih seperti masalah yang muncul untuk programmer Java yang menggunakan kerangka pengembangan Java: Maven, NetBeans, dan Apache Ant, seperti yang Anda lihat dari semua jawaban di sini.
HoldOffHunger

8

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 kasus untuk Gradle build.
Jonathan Landrum

4

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 getDeclaredMethodpanggilan 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 TestUtilitieskelas untuk mengekstrak bidang untuk verifikasi pengujian. (Umumnya dengan kode lawas yang tidak dirancang dengan pengujian unit dalam pikiran.)


3

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

  • tomcat / common / lib
  • mywebapp / WEB-INF / lib

2

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)


2

Ini berarti masing-masing metode tidak ada di kelas:

  1. Jika Anda menggunakan jar maka dekompilasi dan periksa apakah versi masing-masing jar memiliki kelas yang tepat.
  2. Periksa apakah Anda telah mengkompilasi kelas yang tepat dari sumber Anda.

2

Bagi saya itu terjadi karena saya mengubah tipe argumen dalam fungsi, dari Object a, ke String a. Saya bisa menyelesaikannya dengan bersih dan membangun lagi


2

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.


2

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.


2

Hanya menambah jawaban yang ada. Saya menghadapi masalah ini dengan kucing jantan dalam gerhana. Saya telah mengubah satu kelas dan melakukan langkah-langkah berikut,

  1. Membersihkan dan membangun proyek di eclpise

  2. bersihkan instalasi

  3. Kucing jantan yang direstart

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


1

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.

  1. Jika itu terjadi di run time, periksa kelas yang berisi metode ini di jalur kelas.
  2. Periksa apakah Anda telah menambahkan versi JAR baru dan metode ini kompatibel.

1

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 punya masalah serupa. Saya memiliki kelas ketergantungan dengan nama kanonik lengkap yang sama. Setelah mengganti nama pengecualian pergi.
moralejaSinCuentoNiProverbio

1

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+Uatau 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.

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

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.


1

Dalam kasus saya, saya memiliki proyek multi-modul dan skenario seperti com.xyz.TestClassdalam modul Adan juga dalam modul Bdan modul Atergantung 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.

Terkait: https://reflectoring.io/nosuchmethod/


0

Saya mengalami masalah yang sama ketika saya mengubah tanda tangan metode dalam aplikasi saya. Membersihkan dan membangun kembali proyek saya menyelesaikan "NoSuchMethodError".


0

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.


0

Saya mengalami masalah serupa.

Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I

Akhirnya saya mengidentifikasi akar penyebabnya adalah mengubah tipe data variabel.

  1. Employee.java-> Berisi variabel ( EmpId) yang Tipe datanya telah diubah dari intmenjadi String.
  2. ReportGeneration.java-> Mengambil nilai menggunakan pengambil getEmpId(),.

Kita seharusnya menyatukan kembali toples dengan memasukkan hanya kelas yang dimodifikasi. Karena tidak ada perubahan pada ReportGeneration.javasaya hanya termasuk file Employee.classin Jar. Saya harus memasukkan ReportGeneration.classfile ke dalam toples untuk menyelesaikan masalah.


0

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)]



0

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.


0

Masalah dalam kasus saya adalah memiliki dua versi dari perpustakaan yang sama di jalur build. Versi perpustakaan yang lebih lama tidak memiliki fungsi, dan yang lebih baru memilikinya.


0

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


0

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.


-2

Jika nama file Anda berbeda dari nama kelas yang berisi metode utama maka kemungkinan kesalahan ini dapat terjadi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.