Nguyên nhân và sự khác biệt giữa NoClassDefFoundError và ClassNotFoundException là gì?


371

Sự khác biệt giữa NoClassDefFoundErrorvà là ClassNotFoundExceptiongì?

Điều gì khiến chúng bị ném? Làm thế nào họ có thể được giải quyết?

Tôi thường gặp những lỗi này khi sửa đổi mã hiện có để bao gồm các tệp jar mới. Tôi đã đánh chúng ở cả phía máy khách và phía máy chủ cho một ứng dụng java được phân phối thông qua webstart.

Những lý do có thể tôi đã đi qua:

  1. các gói không được bao gồm trong build.xmlphía máy khách của mã
  2. thiếu classpath thời gian chạy cho các lọ mới mà chúng ta đang sử dụng
  3. phiên bản xung đột với jar trước

Khi tôi gặp những điều này ngày hôm nay, tôi thực hiện một cách tiếp cận lỗi và để mọi thứ hoạt động. Tôi cần sự rõ ràng và hiểu biết hơn.


Tôi thường thấy việc chạy JVM với -verbose(ví dụ -verbose:class -verbose:jni) giúp - nhưng mogsie báo cáo bên dưới câu trả lời của họ rằng điều này không cung cấp thêm thông tin hữu ích nào :(
PJTraill

Câu trả lời:


388

Sự khác biệt từ Thông số kỹ thuật API Java như sau.

Dành cho ClassNotFoundException:

Ném khi một ứng dụng cố gắng tải trong một lớp thông qua tên chuỗi của nó bằng cách sử dụng:

  • Các forNamephương thức trong lớp Class.
  • Các findSystemClassphương thức trong lớp ClassLoader.
  • Các loadClassphương thức trong lớp ClassLoader.

nhưng không có định nghĩa cho lớp có tên được chỉ định có thể được tìm thấy.

Dành cho NoClassDefFoundError:

Ném nếu Máy ảo Java hoặc một ClassLoadercá thể cố tải trong định nghĩa của một lớp (như một phần của một cuộc gọi phương thức thông thường hoặc là một phần của việc tạo một cá thể mới bằng cách sử dụng biểu thức mới) và không thể tìm thấy định nghĩa của lớp.

Định nghĩa lớp tìm kiếm tồn tại khi lớp hiện đang được biên dịch, nhưng định nghĩa không thể tìm thấy nữa.

Vì vậy, có vẻ như NoClassDefFoundErrorxảy ra khi nguồn được biên dịch thành công, nhưng trong thời gian chạy, các classtệp yêu cầu không được tìm thấy. Đây có thể là điều có thể xảy ra trong việc phân phối hoặc sản xuất các tệp JAR, trong đó không classbao gồm tất cả các tệp cần thiết .

Về phần ClassNotFoundException, có vẻ như nó có thể xuất phát từ việc cố gắng thực hiện các cuộc gọi phản chiếu đến các lớp trong thời gian chạy, nhưng các lớp mà chương trình đang cố gắng gọi không tồn tại.

Sự khác biệt giữa hai là một Errorvà một là một Exception. Với NoClassDefFoundErrorlà một Errorvà nó phát sinh từ Máy ảo Java có vấn đề khi tìm một lớp mà nó dự kiến ​​sẽ tìm thấy. Một chương trình được dự kiến ​​sẽ hoạt động ở thời gian biên dịch không thể chạy do các classtệp không được tìm thấy hoặc không giống như được sản xuất hoặc gặp phải tại thời gian biên dịch. Đây là một lỗi khá nghiêm trọng, vì chương trình không thể được khởi chạy bởi JVM.

Mặt khác, ClassNotFoundExceptionnó là một Exception, vì vậy nó có phần được mong đợi, và là thứ có thể phục hồi được. Việc sử dụng sự phản chiếu có thể dễ bị lỗi (vì có một số kỳ vọng rằng mọi thứ có thể không diễn ra như mong đợi. Không có kiểm tra thời gian biên dịch để thấy rằng tất cả các lớp bắt buộc tồn tại, do đó, bất kỳ vấn đề nào với việc tìm các lớp mong muốn sẽ xuất hiện trong thời gian chạy .


53
NoClassDefFoundErrorthường xảy ra khi có sự cố (ném ngoại lệ) với khối tĩnh hoặc khởi tạo trường tĩnh của lớp, vì vậy lớp không thể được khởi tạo thành công.
Dagang

7
nâng cao. một là một Errorvà một là một Exception. :)
Ravi

83

ClassNotFoundException được ném khi lớp ClassLoader không tìm thấy. Điều này thường có nghĩa là lớp bị thiếu trong CLASSPATH. Điều đó cũng có thể có nghĩa là lớp trong câu hỏi đang cố gắng được tải từ một lớp khác được tải trong trình nạp lớp cha và do đó lớp từ trình nạp lớp con không hiển thị. Điều này đôi khi xảy ra khi làm việc trong các môi trường phức tạp hơn như Máy chủ ứng dụng (WebSphere nổi tiếng với các vấn đề về trình nạp lớp như vậy).

Mọi người thường có xu hướng nhầm lẫn java.lang.NoClassDefFoundErrorvới java.lang.ClassNotFoundExceptiontuy nhiên có một sự khác biệt quan trọng. Ví dụ: một ngoại lệ (một lỗi thực sự java.lang.NoClassDefFoundErrorlà một lớp con của java.lang.Error) như

java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory

không có nghĩa là lớp ActiveMQConnectionFactory không có trong CLASSPATH. Nguyên vẹn nó hoàn toàn ngược lại. Điều đó có nghĩa là lớp ActiveMQConnectionFactory đã được ClassLoader tìm thấy, tuy nhiên khi cố gắng tải lớp, nó đã gặp phải lỗi khi đọc định nghĩa lớp. Điều này thường xảy ra khi lớp trong câu hỏi có các khối hoặc thành viên tĩnh sử dụng Lớp mà ClassLoader không tìm thấy. Vì vậy, để tìm ra thủ phạm, hãy xem nguồn của lớp đang nghi vấn (ActiveMQConnectionFactory trong trường hợp này) và tìm mã bằng cách sử dụng các khối tĩnh hoặc thành viên tĩnh. Nếu bạn không có quyền truy cập vào nguồn, thì chỉ cần dịch ngược nó bằng JAD.

Khi kiểm tra mã, giả sử bạn tìm thấy một dòng mã như bên dưới, hãy đảm bảo rằng lớp someClass trong CLASSPATH của bạn.

private static SomeClass foo = new SomeClass();

Mẹo: Để tìm hiểu jar thuộc về lớp nào, bạn có thể sử dụng trang web jar Downloader. Điều này cho phép bạn chỉ định một tên lớp bằng cách sử dụng ký tự đại diện và nó tìm kiếm lớp trong cơ sở dữ liệu của các lọ. jarhoo cho phép bạn làm điều tương tự nhưng nó không còn miễn phí để sử dụng.

Nếu bạn muốn xác định vị trí mà một lớp thuộc về một đường dẫn cục bộ, bạn có thể sử dụng một tiện ích như jarscan ( http://www.inetfeedback.com/jarscan/ ). Bạn chỉ cần chỉ định lớp bạn muốn định vị và đường dẫn thư mục gốc nơi bạn muốn nó bắt đầu tìm kiếm lớp trong tệp và tệp zip.


9
Thật buồn cười khi đây là câu trả lời chính xác được bình chọn cuối cùng. (Ngay cả -1 trước khi tôi bỏ phiếu). ClassNotFoundException có nghĩa là CL không nhìn thấy tệp. Class. NoClassDefFoundError có nghĩa là tệp. Class ở đó không tải được (có thể là lỗi JNI).
user43685

1
Không phải câu trả lời này mâu thuẫn với mẫu câu trả lời sao?
zardosht

Tôi đã thử ví dụ tương tự của khối tĩnh. Lớp Class1 của tôi có biến tĩnh "private static B foo = new B ();" Sau khi biên dịch, tôi loại bỏ tệp B.group khỏi thư mục bin. Bây giờ từ phương thức chính của lớp thứ ba khi tôi tạo đối tượng của Class1. Rror được phát triển dưới dạng follws: -------- "Ngoại lệ trong luồng" chính "java.lang.NoClassDefFoundError: spring / B" ........ Vì vậy, nó đề cập chính xác đến lớp mà nó không tìm thấy ieclass được gọi trong khối tĩnh chứ không phải lớp bên ngoài. Vì vậy, nó trái với câu trả lời này.
Kaushik Lele

+1 để làm rõ về "không có nghĩa là lớp ActiveMQConnectionFactory không có trong CLASSPATH"
akila

35

NoClassDefFoundErrorlà một lỗi liên kết về cơ bản. Nó xảy ra khi bạn thử và khởi tạo một đối tượng (tĩnh với "mới") và nó không được tìm thấy khi nó đang trong quá trình biên dịch.

ClassNotFoundExceptionnói chung hơn và là một ngoại lệ thời gian chạy khi bạn cố gắng sử dụng một lớp không tồn tại. Ví dụ: bạn có một tham số trong hàm chấp nhận giao diện và ai đó chuyển vào một lớp thực hiện giao diện đó nhưng bạn không có quyền truy cập vào lớp. Nó cũng bao gồm trường hợp tải lớp động, chẳng hạn như sử dụng loadClass()hoặc Class.forName().


29

NoClassDefFoundError (NCDFE) xảy ra khi mã của bạn chạy "new Y ()" và nó không thể tìm thấy lớp Y.

Có thể đơn giản là Y bị thiếu trong trình tải lớp của bạn như các bình luận khác đề xuất, nhưng có thể là lớp Y không được ký hoặc có chữ ký không hợp lệ hoặc Y được tải bởi một trình nạp lớp khác không hiển thị với mã của bạn hoặc thậm chí Y phụ thuộc vào Z không thể được tải vì bất kỳ lý do nào ở trên.

Nếu điều này xảy ra, thì JVM sẽ ghi nhớ kết quả của việc tải X (NCDFE) và nó sẽ chỉ ném một NCDFE mới mỗi khi bạn yêu cầu Y mà không cho bạn biết lý do:

lớp một {
  lớp tĩnh b {}
  public static void main (String args []) {
    System.out.println ("Lần thử đầu tiên mới b ():");
    thử {mới b (); } bắt (Có thể ném t) {t.printStackTrace ();}
    System.out.println ("\ nSecond thử mới b ():");
    thử {mới b (); } bắt (Có thể ném t) {t.printStackTrace ();}
  }
}

lưu cái này dưới dạng a.java ở đâu đó

Mã chỉ đơn giản là cố gắng khởi tạo một lớp "b" mới hai lần, ngoài ra, nó không có bất kỳ lỗi nào và nó không làm gì cả.

Biên dịch mã với javac a.java, sau đó chạy a bằng cách gọi java -cp . a- nó chỉ cần in ra hai dòng văn bản và nó sẽ chạy tốt mà không có lỗi.

Sau đó xóa tệp "a $ b. Class" (hoặc lấp đầy nó bằng rác hoặc sao chép a. Class qua nó) để mô phỏng lớp bị thiếu hoặc bị hỏng. Đây là những gì xảy ra:

Lần đầu tiên thử b () mới:
java.lang.NoClassDefFoundError: a $ b
    tại a.main (a.java giáp)
Nguyên nhân bởi: java.lang.ClassNotFoundException: a $ b
    tại java.net.URLClassLoader $ 1.run (URLClassLoader.java:200)
    tại java.security.AccessControll.doPriv đặc biệt (Phương thức gốc)
    tại java.net.URLClassLoader.findClass (URLClassLoader.java:188)
    tại java.lang.ClassLoader.loadClass (ClassLoader.java:307)
    tại sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:602)
    tại java.lang.ClassLoader.loadClass (ClassLoader.java:252)
    tại java.lang.ClassLoader.loadClassI Internalal (ClassLoader.java:320)
    ... 1 nữa

Lần thử thứ hai mới b ():
java.lang.NoClassDefFoundError: a $ b
    tại a.main (a.java:7)

Lệnh gọi đầu tiên dẫn đến ClassNotFoundException (được trình tải lớp ném khi nó không thể tìm thấy lớp), phải được bọc trong một NoClassDefFoundError không được kiểm tra, vì mã trong câu hỏi ( new b()) sẽ chỉ hoạt động.

Lần thử thứ hai tất nhiên cũng sẽ thất bại, nhưng như bạn có thể thấy ngoại lệ được bao bọc không còn nữa, bởi vì ClassLoader dường như nhớ các trình nạp lớp không thành công. Bạn chỉ thấy NCDFE hoàn toàn không có manh mối gì về những gì thực sự đã xảy ra.

Vì vậy, nếu bạn từng thấy một NCDFE không có nguyên nhân gốc, bạn cần xem liệu bạn có thể theo dõi lại lần đầu tiên lớp được tải để tìm nguyên nhân gây ra lỗi không.


Điều gì về việc chạy JVM với -verbose, hoặc một số tùy chọn tương tự tùy thuộc vào JVM cụ thể? Có lẽ -verbose:class, có thể -verbose:class:jninếu sử dụng JNI, nhưng tôi không chắc về cú pháp. Nếu điều này hữu ích, có lẽ bạn có thể hiển thị kết quả.
PJTraill

Cả -verbose:classcũng không -verbose:jniđưa ra bất cứ công suất tăng thêm liên quan đến lớp mất tích.
mogsie

1
Cảm ơn bạn đã thử nó, ngay cả khi kết quả là đáng thất vọng. (PS tôi đã phát hiện ra điều đó -verbose:class:jnilà sai: người ta phải chỉ định hai tùy chọn riêng biệt : -verbose:class -verbose:jni.)
PJTraill

2
Câu cuối cùng * 1.000.000: Vì vậy, nếu bạn từng thấy một NCDFE không có nguyên nhân gốc, bạn cần xem liệu bạn có thể theo dõi lại lần đầu tiên lớp được tải để tìm nguyên nhân lỗi không.
batwad

20

Từ http://www.javaroots.com/2013/02/ classnotfoundexception-vs.html :

ClassNotFoundException: xảy ra khi trình nạp lớp không thể tìm thấy lớp được yêu cầu trong đường dẫn lớp. Vì vậy, về cơ bản, bạn nên kiểm tra đường dẫn lớp của bạn và thêm lớp trong đường dẫn lớp.

NoClassDefFoundError: điều này là khó khăn hơn để gỡ lỗi và tìm lý do. Điều này được ném khi tại thời điểm biên dịch các lớp được yêu cầu có mặt, nhưng tại thời điểm chạy, các lớp được thay đổi hoặc loại bỏ hoặc khởi tạo tĩnh của lớp đã ném ngoại lệ. Nó có nghĩa là lớp đang được tải có mặt trong classpath, nhưng một trong những lớp được yêu cầu bởi lớp này hoặc bị loại bỏ hoặc không tải được trình biên dịch. Vì vậy, bạn sẽ thấy các lớp phụ thuộc vào lớp này.

Ví dụ :

public class Test1
{
}


public class Test 
{
   public static void main(String[] args)
   {
        Test1 = new Test1();    
   }

}

Bây giờ sau khi biên dịch cả hai lớp, nếu bạn xóa tệp Test1. Class và chạy lớp Test, nó sẽ ném

Exception in thread "main" java.lang.NoClassDefFoundError: Test
    at Test1.main(Test1.java:5)
Caused by: java.lang.ClassNotFoundException: Test
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 1 more

ClassNotFoundException: bị ném khi một ứng dụng cố tải trong một lớp thông qua tên của nó, nhưng không tìm thấy định nghĩa nào cho lớp có tên được chỉ định.

NoClassDefFoundError: bị ném nếu Máy ảo Java cố tải trong định nghĩa của một lớp và không tìm thấy định nghĩa nào của lớp.


Điều gì về việc chạy JVM với -verbose, hoặc một số tùy chọn tương tự tùy thuộc vào JVM cụ thể? Có lẽ -verbose:class, có thể -verbose:class:jninếu sử dụng JNI, nhưng tôi không chắc về cú pháp.
PJTraill

-verbose:class:jnilà sai, nhưng bạn có thể vượt qua hai tùy chọn riêng biệt : -verbose:class -verbose:jni.
PJTraill

15

Lý do để có được mỗi người trong số họ và bất kỳ quá trình suy nghĩ về cách xử lý các lỗi như vậy là gì?

Chúng có liên quan chặt chẽ với nhau. A ClassNotFoundExceptionbị ném khi Java đi tìm một lớp cụ thể theo tên và không thể tải thành công. A NoClassDefFoundErrorbị ném khi Java tìm kiếm một lớp được liên kết với một số mã hiện có, nhưng không thể tìm thấy nó vì lý do này hay lý do khác (ví dụ: đường dẫn sai, phiên bản sai của Java, phiên bản sai của thư viện) và hoàn toàn gây tử vong vì nó chỉ ra rằng một cái gì đó đã đi sai.

Nếu bạn có nền tảng C, CNFE giống như lỗi dlopen()/ dlsym()và NCDFE là một vấn đề với trình liên kết; trong trường hợp thứ hai, các tệp lớp liên quan không bao giờ được biên dịch thực sự trong cấu hình mà bạn đang cố sử dụng chúng.


11

Ví dụ 1:

class A{
 void met(){
   Class.forName("com.example.Class1");
 }
}

Nếu com/example/Class1không tồn tại trong bất kỳ classpath nào, thì nó sẽ ném ClassNotFoundException.

Ví dụ # 2:

Class B{
  void met(){
   com.example.Class2 c = new com.example.Class2();
 }
}

Nếu com/example/Class2tồn tại trong khi biên dịch B, nhưng không tìm thấy trong khi thực thi, thì nó ném NoClassDefFoundError.

Cả hai đều là ngoại lệ thời gian chạy.


9

ClassNotFoundException được ném khi có nỗ lực tải lớp bằng cách tham chiếu nó qua Chuỗi. Ví dụ, tham số trong Class.forName () là một Chuỗi và điều này làm tăng tiềm năng của các tên nhị phân không hợp lệ được truyền cho trình nạp lớp.

ClassNotFoundException được ném khi gặp tên nhị phân không hợp lệ; chẳng hạn, nếu tên lớp có ký tự '/', bạn nhất định sẽ nhận được ClassNotFoundException. Nó cũng được ném khi lớp tham chiếu trực tiếp không có sẵn trên đường dẫn lớp.

Mặt khác, NoClassDefFoundError bị ném

  • khi biểu diễn vật lý thực tế của lớp - tệp. class không có sẵn,
  • hoặc lớp đã được tải trong một trình nạp lớp khác (thường thì trình nạp lớp cha sẽ tải lớp và do đó lớp không thể được tải lại),
  • hoặc nếu một định nghĩa lớp không tương thích đã được tìm thấy - tên trong tệp lớp không khớp với tên được yêu cầu,
  • hoặc (quan trọng nhất) nếu một lớp phụ thuộc không thể được định vị và tải. Trong trường hợp này, lớp được tham chiếu trực tiếp có thể đã được định vị và tải, nhưng lớp phụ thuộc không có sẵn hoặc không thể tải được. Đây là một kịch bản trong đó lớp được tham chiếu trực tiếp có thể được tải thông qua Class.forName hoặc các phương thức tương đương. Điều này cho thấy sự thất bại trong liên kết.

Nói tóm lại, NoClassDefFoundError thường được ném vào các câu lệnh () hoặc các yêu cầu phương thức mới tải một lớp vắng mặt trước đó (trái ngược với việc tải các lớp dựa trên chuỗi cho ClassNotFoundException), khi trình nạp lớp không thể tìm hoặc tải định nghĩa lớp ( S).

Cuối cùng, tùy thuộc vào việc triển khai ClassLoader để ném một thể hiện của ClassNotFoundException khi nó không thể tải một lớp. Hầu hết các triển khai trình nạp lớp tùy chỉnh thực hiện việc này vì chúng mở rộng URLClassLoader. Thông thường các trình nạp lớp không ném NoClassDefFoundError một cách rõ ràng vào bất kỳ triển khai phương thức nào - ngoại lệ này thường được ném từ JVM trong trình biên dịch HotSpot chứ không phải bởi chính trình nạp lớp.


Upvote để đề cập đến 'tên trong tệp lớp không khớp với tên được yêu cầu'. Đây là một nguyên nhân khá phổ biến.
Hầu tước Lorne

8

Sự khác biệt giữa ClassNotFoundException Vs NoClassDefFoundError

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


Không tinh thể rõ ràng. "Không cập nhật trong classpath" là mơ hồ / không chính xác. Đây là về việc JAR không có mặt trong đường dẫn lớp hoặc phiên bản sai của JAR nằm trên đường dẫn lớp. Và lỗi chính tả. Và (thở dài) vì bạn đã đăng thông tin của mình dưới dạng đồ họa ngộ nghĩnh, chúng tôi không thể sửa lỗi này.
Stephen C

8

Với chính tên chúng ta có thể dễ dàng xác định một từ Exceptionvà một tên khác là từ Error.

Ngoại lệ: Ngoại lệ xảy ra trong quá trình thực hiện chương trình. Một lập trình viên có thể xử lý các ngoại lệ này bằng cách thử khối bắt. Chúng tôi có hai loại ngoại lệ. Đã kiểm tra ngoại lệ ném vào thời gian biên dịch. Thời gian chạy ngoại lệ được ném vào thời gian chạy, những ngoại lệ này thường xảy ra do lập trình xấu.

Lỗi: Đây hoàn toàn không phải là ngoại lệ, nó nằm ngoài phạm vi của lập trình viên. Các lỗi này thường được ném bởi JVM.


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

Sự khác biệt:

ClassNotFoundException:

  • Trình tải lớp không thể xác minh mã byte lớp mà chúng tôi đề cập trong Giai đoạn liên kết của hệ thống con tải lớp mà chúng tôi nhận được ClassNotFoundException.
  • ClassNotFoundExceptionlà một Ngoại lệ được kiểm tra có nguồn gốc trực tiếp từ java.lang.Exceptionlớp và bạn cần cung cấp xử lý rõ ràng cho nó
  • ClassNotFoundExceptionxuất hiện khi có một lớp tải rõ ràng có liên quan bằng cách cung cấp tên của lớp khi chạy bằng ClassLoader.loadClass (), Class.forName () và ClassLoader.findSystemClass ().

NoClassDefFoundError:

  • Trình tải lớp không giải quyết được các tham chiếu của một lớp trong giai đoạn Liên kết của hệ thống con tải lớp mà chúng ta nhận được NoClassDefFoundError.
  • NoClassDefFoundErrorlà một lỗi xuất phát từ LinkageErrorlớp, được sử dụng để chỉ ra các trường hợp lỗi, trong đó một lớp có sự phụ thuộc vào một số lớp khác và lớp đó đã thay đổi một cách không thể thay đổi sau khi biên dịch.
  • NoClassDefFoundErrorlà kết quả của việc tải lớp ngầm vì một lệnh gọi phương thức từ lớp đó hoặc bất kỳ truy cập biến nào.

Điểm tương đồng:

  • Cả hai NoClassDefFoundErrorClassNotFoundExceptioncó liên quan đến sự không có sẵn của một lớp học trong thời gian chạy.
  • Cả hai ClassNotFoundExceptionNoClassDefFoundErrorcó liên quan đến đường dẫn Java.

3

Đưa ra các hành động sussystem của trình nạp lớp:

http://www.artima.com/insidejvm/ed2/images/fig7-1.gif

Đây là một bài viết giúp tôi rất nhiều để hiểu sự khác biệt: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

Nếu xảy ra lỗi trong khi tải lớp, thì một thể hiện của một lớp con của LinkageError phải được ném vào một điểm trong chương trình (trực tiếp hoặc gián tiếp) sử dụng lớp hoặc giao diện được tải.

Nếu Máy ảo Java từng cố tải một lớp C trong khi xác minh (§5.4.1) hoặc độ phân giải (§5.4.3) (nhưng không khởi tạo (§5.5)) và trình nạp lớp được sử dụng để bắt đầu tải C ném một cá thể của ClassNotFoundException , sau đó Máy ảo Java phải ném một cá thể của NoClassDefFoundError mà nguyên nhân là cá thể của ClassNotFoundException .

Vì vậy, ClassNotFoundException là nguyên nhân gốc của NoClassDefFoundError .
NoClassDefFoundError là trường hợp đặc biệt của lỗi tải loại, xảy ra ở bước Liên kết .


2

Thêm một lý do có thể trong thực tế:

  • ClassNotFoundException: như cletus đã nói, bạn sử dụng giao diện trong khi lớp giao diện được kế thừa không nằm trong đường dẫn lớp. Ví dụ: Mẫu nhà cung cấp dịch vụ (hoặc Trình định vị dịch vụ ) cố gắng định vị một số lớp không tồn tại
  • NoClassDefFoundError: lớp đã cho được tìm thấy trong khi không tìm thấy sự phụ thuộc của lớp đã cho

Trong thực tế, Lỗi có thể được ném âm thầm , ví dụ: bạn gửi một tác vụ hẹn giờ và trong tác vụ hẹn giờ, nó sẽ ném Lỗi , trong khi trong hầu hết các trường hợp, chương trình của bạn chỉ bắt Ngoại lệ . Sau đó, vòng lặp chính Timer kết thúc mà không có bất kỳ thông tin nào. Một lỗi tương tự với NoClassDefFoundError là ExceptionInInialialError , khi trình khởi tạo tĩnh hoặc trình khởi tạo cho biến tĩnh của bạn đưa ra một ngoại lệ.


1

ClassNotFoundException là một ngoại lệ được kiểm tra xảy ra khi chúng ta yêu cầu JVM tải một lớp bằng tên chuỗi của nó bằng cách sử dụng các phương thức Class.forName () hoặc ClassLoader.findSystemClass () hoặc ClassLoader.loadClass () và lớp được đề cập trong lớp đường dẫn.

Hầu hết thời gian, ngoại lệ này xảy ra khi bạn cố chạy một ứng dụng mà không cập nhật đường dẫn lớp với các tệp JAR được yêu cầu. Ví dụ, bạn có thể đã thấy ngoại lệ này khi thực hiện mã JDBC để kết nối với cơ sở dữ liệu của bạn tức là MYQuery nhưng đường dẫn lớp của bạn không có JAR cho nó.

Lỗi NoClassDefFoundError xảy ra khi JVM cố tải một lớp cụ thể là một phần của việc thực thi mã của bạn (như một phần của lệnh gọi phương thức thông thường hoặc là một phần của việc tạo một cá thể bằng từ khóa mới) và lớp đó không có trong đường dẫn lớp của bạn nhưng có mặt tại thời gian biên dịch vì để thực thi chương trình của bạn, bạn cần biên dịch nó và nếu bạn đang cố gắng sử dụng một lớp không có trình biên dịch sẽ gây ra lỗi biên dịch.

Dưới đây là mô tả ngắn gọn

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

Bạn có thể đọc mọi thứ về ClassNotFoundException Vs NoClassDefFoundError để biết thêm chi tiết.


0

Tôi nhắc nhở bản thân những điều sau đây lặp đi lặp lại khi tôi cần làm mới

ClassNotFoundException

Phân cấp lớp

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

Trong khi gỡ lỗi

  1. Yêu cầu jar, lớp bị thiếu từ đường dẫn lớp.
  2. Xác nhận tất cả các lọ cần thiết trong classpath của jvm.

NoClassDefFoundError

Phân cấp lớp

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

Trong khi gỡ lỗi

  1. Vấn đề với việc tải một lớp động, được biên dịch đúng
  2. Sự cố với các khối tĩnh, hàm tạo, phương thức init () của lớp phụ thuộc và lỗi thực tế được bao bọc bởi nhiều lớp [đặc biệt là khi bạn sử dụng lò xo, ngủ đông ngoại lệ thực tế được bọc và bạn sẽ nhận được NoClassDefError]
  3. Khi bạn đối mặt với "ClassNotFoundException" trong một khối tĩnh của lớp phụ thuộc
  4. Vấn đề với các phiên bản của lớp. Điều này xảy ra khi bạn có hai phiên bản v1, v2 cùng loại trong các gói / gói khác nhau, được biên dịch thành công khi sử dụng v1 và v2 được tải trong thời gian chạy không có các phương thức / vars có liên quan và bạn sẽ thấy ngoại lệ này. [Tôi đã từng giải quyết vấn đề này bằng cách xóa bản sao của lớp liên quan đến log4j dưới nhiều tệp xuất hiện trong đường dẫn lớp]

-1

ClassNotFoundException và NoClassDefFoundError xảy ra khi một lớp cụ thể không được tìm thấy trong thời gian chạy. Tuy nhiên, chúng xảy ra ở các kịch bản khác nhau.

ClassNotFoundException là một ngoại lệ xảy ra khi bạn cố tải một lớp trong thời gian chạy bằng cách sử dụng các phương thức Class.forName () hoặc loadClass () và các lớp được đề cập không tìm thấy trong đường dẫn lớp.

    public class MainClass
    {
        public static void main(String[] args)
        {
            try
            {
                Class.forName("oracle.jdbc.driver.OracleDriver");
            }catch (ClassNotFoundException e)
            {
                e.printStackTrace();
            }
        }
    }



    java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at pack1.MainClass.main(MainClass.java:17)

NoClassDefFoundError là một lỗi xảy ra khi một lớp cụ thể có mặt tại thời gian biên dịch, nhưng bị thiếu trong thời gian chạy.

    class A
    {
      // some code
    }
    public class B
    {
        public static void main(String[] args)
        {
            A a = new A();
        }
    }

Khi bạn biên dịch chương trình trên, hai tệp. Class sẽ được tạo. Một là A. class và một cái khác là B. class. Nếu bạn xóa tệp A. class và chạy tệp B. class, Java Runtime System sẽ ném NoClassDefFoundError như bên dưới:

    Exception in thread "main" java.lang.NoClassDefFoundError: A
    at MainClass.main(MainClass.java:10)
    Caused by: java.lang.ClassNotFoundException: A
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
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.