Làm cách nào để sửa lỗi NoSuchMethodError?


177

Tôi đang gặp NoSuchMethodErrorlỗi khi chạy chương trình Java của mình. Có gì sai và làm cách nào để sửa nó?


11
Trong Netbeans: Nhấp chuột phải vào dự án trong tab Dự án, sử dụng "Làm sạch và Xây dựng". Giải quyết nó cho tôi.
Heinzlmaen

3
Cũng trong Intellij Idea, việc xây dựng lại đôi khi giải quyết vấn đề
Hawk

1
Bài viết này rất hữu ích cho vấn đề này Reflectoring.io/nosuchmethod
Michael Smith

Câu trả lời:


227

Nếu không có thêm thông tin thì rất khó xác định vấn đề, nhưng nguyên nhân sâu xa là rất có thể bạn đã biên dịch một lớp đối với một phiên bản khác của lớp đang thiếu một phương thức, so với phương thức bạn đang sử dụng khi chạy nó.

Nhìn vào dấu vết ngăn xếp ... Nếu ngoại lệ xuất hiện khi gọi một phương thức trên một đối tượng trong thư viện, rất có thể bạn đang sử dụng các phiên bản riêng biệt của thư viện khi biên dịch và chạy. Hãy chắc chắn rằng bạn có phiên bản phù hợp cả hai nơi.

Nếu ngoại lệ xuất hiện khi gọi một phương thức trên các đối tượng được khởi tạo bởi các lớp bạn đã tạo, thì quá trình xây dựng của bạn dường như bị lỗi. Hãy chắc chắn rằng các tệp lớp mà bạn thực sự đang chạy được cập nhật khi bạn biên dịch.


3
Gần đây chúng tôi đã phát hiện ra nguyên nhân của một trong những điều này và hóa ra quá trình xây dựng đã đặt các tệp lớp vào vị trí trước khi máy chủ java bị tắt và chúng tôi nhấn vào điều này vì máy chủ java đã tải một số lớp và sau đó nó đã tải một số nhưng nó có những cái mới này và vì mã mới đề cập đến các phương thức mà các lớp cũ không có ... bingo, NoSuchMethodError
vazor

"Nhìn vào dấu vết ngăn xếp ..." - Chà, tôi hầu như luôn luôn đi và kiểm tra phần cuối cùng Caused bytrong dấu vết ngăn xếp để tìm lớp / thủ phạm
KrishPrabakar

108

Tôi đã có vấn đề của bạn, và đây là cách tôi khắc phục nó. Các bước sau đây là một cách làm việc để thêm một thư viện. Tôi đã thực hiện đúng hai bước đầu tiên, nhưng tôi đã không thực hiện bước cuối cùng bằng cách kéo tệp ".jar" trực tiếp từ hệ thống tệp vào thư mục "lib" trong dự án nhật thực của tôi. Ngoài ra, tôi phải xóa phiên bản trước của thư viện khỏi cả đường dẫn xây dựng và thư mục "lib".

Bước 1 - Thêm .jar để xây dựng đường dẫn

nhập mô tả hình ảnh ở đây

Bước 2 - Liên kết các nguồn và javadocs (tùy chọn)

nhập mô tả hình ảnh ở đây

Bước 3 - Thực tế kéo tập tin .jar vào thư mục "lib" (không bắt buộc)

nhập mô tả hình ảnh ở đây


75
+1 cho "Mọi người đều mong bạn biết cách sử dụng nó và nếu bạn không đánh giá thấp câu hỏi của bạn."
Vikram

73

Lưu ý rằng trong trường hợp phản chiếu, bạn nhận được một NoSuchMethodException, trong khi với mã không phản chiếu, bạn nhận được NoSuchMethodError. Tôi có xu hướng đi tìm ở những nơi rất khác nhau khi đối đầu với người này so với người kia.


Nói cách khác, bạn đang nói rằng nếu bạn đang sử dụng sự phản chiếu để có được một phương thức trên một lớp và phương thức không được tìm thấy, bạn sẽ nhận được NoSuchMethodException. Nhưng nếu bạn đang ở trong một kịch bản khi bạn biên dịch mã của mình theo một số lib và trên máy chủ bạn có các lib khác (có thể mới hơn có thể cũ hơn) thì bạn sẽ nhận được NoSuchMethodError. Sửa tôi nếu tôi sai.
Victor

Điều đó đúng, @Victor
KrishPrabakar

51

Nếu bạn có quyền truy cập để thay đổi các tham số JVM, việc thêm đầu ra dài dòng sẽ cho phép bạn xem các lớp nào đang được tải từ các tệp JAR nào.

java -verbose:class <other args>

Khi chương trình của bạn được chạy, JVM sẽ chuyển sang các thông tin tiêu chuẩn như:

...

[Đã tải Junit.framework.Assert từ tệp: / C: /Program%20Files/junit3.8.2/junit.jar]

...


3
+1 Rực rỡ! Tôi đã giải quyết một vấn đề nhỏ khó chịu bằng cách sử dụng phương pháp này, cảm ơn. Đây là một cách tuyệt vời để khám phá khi các lớp đã lẻn vào đường dẫn bằng cách nào đó.
Duncan Jones

1
+1 Bạn đã cứu ngày của tôi! Nó chỉ là một thư viện bao gồm các lớp cũ có cùng tên vào nguồn của nó.
Andrii Nemchenko

12

Điều này thường xảy ra khi sử dụng một hệ thống xây dựng như Apache Ant chỉ biên dịch các tệp java khi tệp java mới hơn tệp lớp. Nếu một chữ ký phương thức thay đổi và các lớp đang sử dụng phiên bản cũ, mọi thứ có thể không được biên dịch chính xác. Cách khắc phục thông thường là xây dựng lại toàn bộ (thường là "kiến sạch" rồi "kiến").

Đôi khi điều này cũng có thể được gây ra khi biên dịch với một phiên bản của thư viện nhưng chạy với một phiên bản khác.


1
Trên thực tế, điều này cảm thấy giống như một vấn đề nảy sinh đối với các lập trình viên Java đang sử dụng bất kỳ khung phát triển Java nào: Maven, NetBeans và Apache Ant, như bạn có thể thấy trong tất cả các câu trả lời ở đây.
Hold OfferHunger 17/03/2016

8

Nếu sử dụng Maven hoặc một khung công tác khác và bạn gặp lỗi này gần như ngẫu nhiên, hãy thử cài đặt sạch như ...

clean install

Điều này đặc biệt có khả năng hoạt động nếu bạn đã viết đối tượng và bạn biết nó có phương thức. Đã làm cho tôi.


Đây cũng là trường hợp cho các bản dựng Gradle.
Jonathan Landrum

4

Đây cũng có thể là kết quả của việc sử dụng sự phản chiếu. Nếu bạn có mã phản ánh trên một lớp và trích xuất một phương thức theo tên (ví dụ: với Class.getDeclaredMethod("someMethodName", .....)) thì bất cứ khi nào tên phương thức đó thay đổi, chẳng hạn như trong một bộ tái cấu trúc, bạn sẽ cần nhớ cập nhật các tham số cho phương thức phản chiếu để khớp với chữ ký phương thức mới, hoặc getDeclaredMethodcuộc gọi sẽ ném a NoSuchMethodException.

Nếu đây là lý do, thì dấu vết ngăn xếp sẽ hiển thị điểm mà phương thức phản chiếu được gọi và bạn sẽ chỉ cần cập nhật các tham số để khớp với chữ ký phương thức thực tế.

Theo kinh nghiệm của tôi, điều này thỉnh thoảng xuất hiện khi đơn vị kiểm tra các phương thức / trường riêng và sử dụng một TestUtilitieslớp để trích xuất các trường để xác minh kiểm tra. (Nói chung với mã kế thừa không được thiết kế với mục đích kiểm tra đơn vị.)


3

Nếu bạn đang viết một ứng dụng web, hãy đảm bảo rằng bạn không có các phiên bản mâu thuẫn trong thư mục thư viện toàn cầu của bạn và cả trong ứng dụng của bạn. Bạn có thể không nhất thiết phải biết jar nào đang được sử dụng bởi trình nạp lớp.

ví dụ

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

2

Những vấn đề này được gây ra bởi việc sử dụng cùng một đối tượng ở cùng hai lớp. Các đối tượng được sử dụng không chứa phương thức mới đã được thêm vào mà lớp đối tượng mới chứa.

Ví dụ:

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$ 

Những vấn đề này được gây ra bởi 02 lớp tương tự (1 trong src, 1 trong tệp jar ở đây là gateway.jar)


2

Nó có nghĩa là phương thức tương ứng không có trong lớp:

  1. Nếu bạn đang sử dụng jar thì dịch ngược và kiểm tra xem phiên bản tương ứng của jar có đúng lớp không.
  2. Kiểm tra nếu bạn đã biên dịch lớp thích hợp từ nguồn của bạn.

2

Đối với tôi, điều đó xảy ra vì tôi đã thay đổi loại đối số trong hàm, từ Object a, sang String a. Tôi có thể giải quyết nó với sạch và xây dựng lại


2

Tôi vừa giải quyết lỗi này bằng cách khởi động lại Eclipse của tôi và chạy ứng dụng. Lý do cho trường hợp của tôi có thể là do tôi thay thế các tệp nguồn của mình mà không đóng dự án hoặc Eclipse. Điều này gây ra phiên bản khác nhau của các lớp tôi đang sử dụng.


2

Hãy thử theo cách này: xóa tất cả các tệp. Class trong thư mục dự án của bạn (và, tất nhiên, tất cả các thư mục con). Xây dựng lại.

Đôi khi mvn clean(nếu bạn đang sử dụng maven) không dọn sạch các tệp. Class được tạo thủ công bởi javac. Và những tập tin cũ chứa chữ ký cũ, dẫn đến NoSuchMethodError.


2

Chỉ cần thêm vào câu trả lời hiện có. Tôi đã phải đối mặt với vấn đề này với tomcat trong nhật thực. Tôi đã thay đổi một lớp và làm theo các bước,

  1. Làm sạch và xây dựng dự án trong eclpise

  2. mvn cài đặt sạch

  3. Đã khởi động lại tomcat

Tôi vẫn phải đối mặt với lỗi tương tự. Sau đó, tôi dọn dẹp tomcat, làm sạch thư mục làm việc tomcat và khởi động lại máy chủ và vấn đề của tôi không còn nữa. Hy vọng điều này sẽ giúp ai đó


1

Để trả lời câu hỏi ban đầu. Theo tài liệu java ở đây :

"NoSuchMethodError" Ném nếu một ứng dụng cố gắng gọi một phương thức được chỉ định của một lớp (tĩnh hoặc thể hiện) và lớp đó không còn định nghĩa về phương thức đó nữa.

Thông thường, lỗi này được trình biên dịch bắt; lỗi này chỉ có thể xảy ra trong thời gian chạy nếu định nghĩa của một lớp đã thay đổi không thể thay đổi.

  1. Nếu nó xảy ra trong thời gian chạy, hãy kiểm tra lớp có chứa phương thức trong đường dẫn lớp.
  2. Kiểm tra xem bạn đã thêm phiên bản mới của JAR chưa và phương thức này có tương thích không.

1

Tôi đã khắc phục vấn đề này trong Eclipse bằng cách đổi tên tệp thử nghiệm Junit.
Trong không gian làm việc Eclipse của tôi, tôi có một dự án Ứng dụng và một dự án thử nghiệm.
Dự án thử nghiệm có dự án Ứng dụng như một dự án bắt buộc trên đường dẫn xây dựng.

Bắt đầu nhận NoSuchMethodError.
Sau đó, tôi nhận ra lớp trong dự án Test có cùng tên với lớp trong dự án Ứng dụng.

App/  
  src/
     com.example/  
       Projection.java
Test/  
  src/
     com.example/
       Projection.java

Sau khi đổi tên Bài kiểm tra thành tên chính xác "ProjectionTest.java", ngoại lệ đã biến mất.


Tôi đã có một vấn đề tương tự. Tôi đã có một lớp phụ thuộc với cùng tên hoàn chỉnh. Sau khi đổi tên ngoại lệ đã biến mất.
moralejaSinCuentoNiProverbio

1

Tôi đã có những lỗi giống nhau:

  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)

Để giải quyết nó, trước tiên, tôi đã kiểm tra Sơ đồ phụ thuộc mô-đun ( click in your POM the combination -> Ctrl+Alt+Shift+Uhoặc right click in your POM -> Maven -> Show dependencies) để hiểu chính xác xung đột giữa các thư viện (Intelij IDEA). Trong trường hợp cụ thể của tôi, tôi đã có các phiên bản khác nhau của Jackson.

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

1) Vì vậy, tôi đã thêm trực tiếp vào POM của dự án một cách rõ ràng phiên bản cao nhất - 2.8.7 của hai dự án này.

Trong tài sản:

<jackson.version>2.8.7</jackson.version>

Và như phụ thuộc:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>

2) Nhưng nó cũng có thể được giải quyết bằng cách sử dụng Loại trừ phụ thuộc .

Theo nguyên tắc tương tự như dưới đây trong ví dụ:

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

Sự phụ thuộc với phiên bản không mong muốn sẽ được loại trừ khỏi dự án của bạn.


1

Trong trường hợp của tôi, tôi đã có một dự án đa mô-đun và kịch bản giống như com.xyz.TestClasstrong mô-đun Avà cũng như trong mô-đun Bvà mô-đun Aphụ thuộc vào mô-đun B. Vì vậy, trong khi tạo một jar lắp ráp, tôi nghĩ rằng chỉ có một phiên bản của lớp được giữ lại nếu đó không có phương thức được gọi thì tôi đã nhận được NoSuchMethodErrorngoại lệ thời gian chạy, nhưng quá trình biên dịch vẫn ổn.

Liên quan: https://reflectoring.io/nosuchmethod/


0

Tôi gặp một vấn đề tương tự khi tôi thay đổi chữ ký phương thức trong ứng dụng của mình. Làm sạch và xây dựng lại dự án của tôi đã giải quyết "NoSuchMethodError".


0

Câu trả lời trên giải thích rất rõ .. chỉ cần thêm một điều Nếu bạn đang sử dụng nhật thực, hãy sử dụng ctrl + shift + T và nhập cấu trúc gói của lớp (ví dụ: gateway.smpp.PDUEventListener), bạn sẽ tìm thấy tất cả các lọ / dự án có mặt . Loại bỏ các lọ không cần thiết khỏi classpath hoặc thêm ở trên trong đường dẫn lớp. Bây giờ nó sẽ chọn đúng.


0

Tôi gặp vấn đề tương tự.

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

Cuối cùng tôi xác định nguyên nhân gốc là thay đổi kiểu dữ liệu của biến.

  1. Employee.java-> Chứa biến ( EmpId) có Kiểu dữ liệu đã được thay đổi từ intthành String.
  2. ReportGeneration.java-> Lấy giá trị bằng cách sử dụng getter , getEmpId().

Chúng tôi có nghĩa vụ phải nạp lại bình bằng cách chỉ bao gồm các lớp đã sửa đổi. Vì không có thay đổi trong ReportGeneration.javatôi nên chỉ bao gồm Employee.classtệp Jar. Tôi đã phải bao gồm các ReportGeneration.classtập tin trong jar để giải quyết vấn đề.


0

Tôi đã có cùng một vấn đề. Điều này cũng được gây ra khi có sự mơ hồ trong các lớp học. Chương trình của tôi đã cố gắng gọi một phương thức có trong hai tệp JAR có trong cùng một đường dẫn vị trí / lớp. Xóa một tệp JAR hoặc thực thi mã của bạn để chỉ một tệp JAR được sử dụng. Kiểm tra xem bạn không sử dụng cùng một JAR hoặc các phiên bản khác nhau của cùng một JAR có chứa cùng một lớp.

DISP_E_EXCEPTION [bước] [] [Z-JAVA-105 ngoại lệ Java java.lang.NoSuchMethodError (com.example.yourmethod)]


0

Hầu hết các lần java.lang.NoSuchMethodError bị bắt là trình biên dịch nhưng đôi khi nó có thể xảy ra khi chạy. Nếu lỗi này xảy ra trong thời gian chạy thì lý do duy nhất có thể là sự thay đổi trong cấu trúc lớp khiến nó không tương thích.

Giải thích tốt nhất: https://www.journaldev.com/14538/java-lang-nosuchmethoderror


0

Tôi cũng đã gặp phải lỗi này.

Vấn đề của tôi là tôi đã thay đổi chữ ký của một phương thức, đại loại như

void invest(Currency money){...}

vào

void invest(Euro money){...}

Phương pháp này được gọi từ một bối cảnh tương tự như

public static void main(String args[]) {
    Bank myBank = new Bank();

    Euro capital = new Euro();
    myBank.invest(capital);
}

Trình biên dịch im lặng liên quan đến các cảnh báo / lỗi, vì vốn là cả Tiền tệ cũng như Euro.

Vấn đề xuất hiện do thực tế là tôi chỉ biên dịch lớp trong đó phương thức được định nghĩa - Ngân hàng, nhưng không phải là lớp mà phương thức đang được gọi từ đó, có chứa phương thức main ().

Vấn đề này không phải là điều bạn có thể gặp phải quá thường xuyên, vì hầu hết các dự án được xây dựng lại một cách thủ công hoặc một hành động Xây dựng được kích hoạt tự động, thay vì chỉ biên dịch một lớp đã sửa đổi.

Usecase của tôi là tôi đã tạo một tệp .jar được sử dụng như một hotfix, không chứa App. Class vì điều này không được sửa đổi. Nó có ý nghĩa với tôi không bao gồm nó khi tôi giữ kế thừa máng lớp cơ sở của đối số ban đầu.

Vấn đề là, khi bạn biên dịch một lớp, mã byte kết quả là loại tĩnh , nói cách khác, đó là một tài liệu tham khảo khó .

Mã byte được phân tách ban đầu (được tạo bằng công cụ javap) trông như thế này:

 #7 = Methodref          #2.#22         // Bank.invest:(LCurrency;)V

Sau khi ClassLoader tải Bank. Class mới được biên dịch, nó sẽ không tìm thấy một phương thức như vậy, nó xuất hiện như thể nó đã bị xóa và không thay đổi, do đó là lỗi được đặt tên.

Hi vọng điêu nay co ich.


0

Vấn đề trong trường hợp của tôi là có hai phiên bản của cùng một thư viện trong đường dẫn xây dựng. Phiên bản cũ hơn của thư viện không có chức năng và phiên bản mới hơn thì có.


0

Tôi gặp vấn đề tương tự với Dự án Gradle của mình khi sử dụng Intelij. Tôi đã giải quyết nó bằng cách xóa Gói .gradle (xem ảnh chụp màn hình bên dưới) và xây dựng lại Dự án. Gói nâng cấp


0

NoSuchMethodError: Tôi đã dành vài giờ để khắc phục sự cố này, cuối cùng đã sửa nó bằng cách đổi tên gói, dọn dẹp và xây dựng ... Hãy thử xây dựng sạch trước nếu nó không hoạt động, hãy thử đổi tên tên lớp hoặc tên gói và xây dựng sạch .. .it nên được sửa chữa. Chúc may mắn.


-2

Nếu tên tệp của bạn khác với tên lớp chứa phương thức chính thì có thể lỗi này có thể gây ra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.