Tôi đang gặp NoSuchMethodError
lỗ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ó?
Tôi đang gặp NoSuchMethodError
lỗ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ó?
Câu trả lời:
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.
Caused by
trong dấu vết ngăn xếp để tìm lớp / thủ phạm
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".
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ế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]
...
Đ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.
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 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 getDeclaredMethod
cuộ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 TestUtilities
lớ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ị.)
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ụ
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)
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.
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
.
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,
Làm sạch và xây dựng dự án trong eclpise
mvn cài đặt sạch
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 đó
Để 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.
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ó 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+U
hoặ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.
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.
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.TestClass
trong mô-đun A
và cũng như trong mô-đun B
và mô-đun A
phụ 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 NoSuchMethodError
ngoạ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/
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.
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.
Employee.java
-> Chứa biến ( EmpId
) có Kiểu dữ liệu đã được thay đổi từ int
thành String
.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.java
tôi nên chỉ bao gồm Employee.class
tệp Jar. Tôi đã phải bao gồm các ReportGeneration.class
tập tin trong jar để giải quyết vấn đề.
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)]
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
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.
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
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.
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.