Bài viết này dành cho những người mới bắt đầu Java hiện đang gặp phải java.lang.ClassNotFoundException challenges. Nó sẽ cung cấp cho bạn một cái nhìn tổng quan về ngoại lệ Java phổ biến này, một chương trình Java mẫu để hỗ trợ quá trình học tập và các chiến lược giải quyết của bạn.

Nếu bạn quan tâm đến các vấn đề liên quan đến trình tải lớp nâng cao hơn, tôi khuyên bạn nên xem lại loạt bài viết của tôi về java.lang.NoClassDefFoundError Ince những ngoại lệ Java này có liên quan chặt chẽ với nhau.

Theo Oracle tài liệu, Class Not Found Exception được đưa ra sau sự cố của một lệnh gọi tải lớp, sử dụng tên chuỗi của nó, như sau:

  • Class.forName
  • ClassLoader.findSystemClass
  • ClassLoader.loadClass

Nói cách khác, nó có nghĩa là một lớp Java cụ thể đã không phải tìm thấy hoặc có thể không phải được tải trong thời gian chạy từ trình tải lớp ngữ cảnh hiện tại của ứng dụng của bạn.

Vấn đề này có thể đặc biệt khó hiểu đối với người mới bắt đầu sử dụng Java. Đây là lý do tại sao tôi luôn khuyên các nhà phát triển Java tìm hiểu và trau dồi kiến ​​thức của họ về bộ tải lớp Java. Trừ khi bạn tham gia vào quá trình tải lớp động và sử dụng Java Reflection APIrất có thể là ClassNotFoundException bạn nhận được không phải từ mã ứng dụng của bạn mà từ một API tham chiếu. Một dạng vấn đề phổ biến khác là đóng gói sai mã ứng dụng của bạn. Chúng ta sẽ quay lại các chiến lược giải quyết ở cuối bài viết.

Chương trình Java cho phép bạn chọn giữa tình huống sự cố số 1 hoặc tình huống sự cố số 2 như bên dưới. Đơn giản chỉ cần thay đổi thành 1 hoặc 2 tùy thuộc vào kịch bản bạn muốn nghiên cứu.

 # Class.forName()
private static final int PROBLEM_SCENARIO = 1;

# ClassLoader.loadClass()
private static final int PROBLEM_SCENARIO = 2;
# ClassNotFoundExceptionSimulator

 package org.ph.javaee.training5;

/**
 * ClassNotFoundExceptionSimulator
 * @author Pierre-Hugues Charbonneau
 *
 */
public class ClassNotFoundExceptionSimulator {

       private static final String CLASS_TO_LOAD = "org.ph.javaee.training5.ClassA";
       private static final int PROBLEM_SCENARIO = 1;

       /**
        * @param args
        */
       public static void main(String[] args) {

             System.out.println("java.lang.ClassNotFoundException Simulator - Training 5");
             System.out.println("Author: Pierre-Hugues Charbonneau");
             System.out.println("http://javaeesupportpatterns.blogspot.com");

             switch(PROBLEM_SCENARIO) {

                    // Scenario #1 - Class.forName()
                    case 1:

                           System.out.println("n** Problem scenario #1: Class.forName() **n");
                           try {
                                 Class<?> newClass = Class.forName(CLASS_TO_LOAD);

                                 System.out.println("Class "+newClass+" found successfully!");

                           } catch (ClassNotFoundException ex) {

                                 ex.printStackTrace();

                                 System.out.println("Class "+CLASS_TO_LOAD+" not found!");

                           } catch (Throwable any) {                           
                                 System.out.println("Unexpected error! "+any);
                           }

                           break;

                    // Scenario #2 - ClassLoader.loadClass()
                    case 2:

                           System.out.println("n** Problem scenario #2: ClassLoader.loadClass() **n");                     
                           try {
                                 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();            
                                 Class<?> callerClass = classLoader.loadClass(CLASS_TO_LOAD);

                                 Object newClassAInstance = callerClass.newInstance();

                                 System.out.println("SUCCESS!: "+newClassAInstance);
                           } catch (ClassNotFoundException ex) {

                                 ex.printStackTrace();

                                 System.out.println("Class "+CLASS_TO_LOAD+" not found!");

                           } catch (Throwable any) {                           
                                 System.out.println("Unexpected error! "+any);
                           }

                           break;
             }

             System.out.println("nSimulator done!");
       }
}
# ClassA

 package org.ph.javaee.training5;

/**
 * ClassA
 * @author Pierre-Hugues Charbonneau
 *
 */
public class ClassA {

private final static Class<ClassA> CLAZZ = ClassA.class;

       static {
             System.out.println("Class loading of "+CLAZZ+" from ClassLoader '"+CLAZZ.getClassLoader()+"' in progress...");
       }

       public ClassA() {
             System.out.println("Creating a new instance of "+ClassA.class.getName()+"...");

             doSomething();
       }

       private void doSomething() {           
             // Nothing to do...
       }
}

Nếu bạn chạy chương trình như hiện tại, bạn sẽ thấy kết quả như bên dưới cho mỗi trường hợp:

#Scenario 1 output (baseline)

java.lang.ClassNotFoundException Simulator - Training 5
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com

** Problem scenario #1: Class.forName() **

Class loading of class org.ph.javaee.training5.ClassA from ClassLoader '[email protected]' in progress...
Class class org.ph.javaee.training5.ClassA found successfully!

Simulator done!

#Scenario 2 output (đường cơ sở)

java.lang.ClassNotFoundException Simulator - Training 5
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com

** Problem scenario #2: ClassLoader.loadClass() **

Class loading of class org.ph.javaee.training5.ClassA from ClassLoader '[email protected]' in progress...
Creating a new instance of org.ph.javaee.training5.ClassA...
SUCCESS!: [email protected]

Simulator done!

Khi chạy đường cơ sở, chương trình Java có thể tải ClassA thành công.

Bây giờ chúng ta hãy tự nguyện thay đổi tên đầy đủ của ClassA và chạy lại chương trình cho từng tình huống. Kết quả sau có thể được quan sát:

#ClassA thay đổi để ClassB

 private static final String CLASS_TO_LOAD = "org.ph.javaee.training5.ClassB";
#Scenario 1 output (nhân rộng vấn đề)

java.lang.ClassNotFoundException Simulator - Training 5
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com

** Problem scenario #1: Class.forName() **

java.lang.ClassNotFoundException: org.ph.javaee.training5.ClassB
       at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
       at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
       at java.security.AccessController.doPrivileged(Native Method)
       at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
       at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
       at java.lang.Class.forName0(Native Method)
       at java.lang.Class.forName(Class.java:186)
       at org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main(ClassNotFoundExceptionSimulator.java:29)
Class org.ph.javaee.training5.ClassB not found!

Simulator done!

#Scenario 2 output (nhân rộng vấn đề)

java.lang.ClassNotFoundException Simulator - Training 5
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com

** Problem scenario #2: ClassLoader.loadClass() **

java.lang.ClassNotFoundException: org.ph.javaee.training5.ClassB
       at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
       at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
       at java.security.AccessController.doPrivileged(Native Method)
       at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
       at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
       at org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main(ClassNotFoundExceptionSimulator.java:51)
Class org.ph.javaee.training5.ClassB not found!

Simulator done!

Chuyện gì đã xảy ra thế? Vì chúng tôi đã thay đổi tên lớp đầy đủ thành org.ph.javaee.training5.ClassB, lớp như vậy không được tìm thấy trong thời gian chạy (không tồn tại), gây ra cả hai Class.forName()ClassLoader.loadClass() cuộc gọi thất bại.

Bạn cũng có thể tái tạo sự cố này bằng cách đóng gói từng lớp của chương trình này thành tệp JAR của riêng nó và sau đó bỏ qua tệp jar chứa ClassA.class khỏi đường dẫn lớp chính. Vui lòng thử điều này và xem kết quả cho chính bạn… (gợi ý: NoClassDefFoundError)

Bây giờ chúng ta hãy chuyển sang các chiến lược giải quyết.

java.lang.ClassNotFoundException: Resolution strategies

Bây giờ bạn đã hiểu vấn đề này, bây giờ là lúc để giải quyết nó. Việc giải quyết có thể khá đơn giản hoặc rất phức tạp tùy thuộc vào nguyên nhân gốc rễ.

  • Đừng nhảy vào những nguyên nhân gốc phức tạp quá nhanh, hãy loại trừ những nguyên nhân đơn giản nhất trước.
  • Đầu tiên hãy xem lại java.lang.ClassNotFoundException theo dõi theo cách trên và xác định lớp Java nào không được tải đúng cách trong thời gian chạy, ví dụ như mã ứng dụng, API của bên thứ ba, bản thân vùng chứa Java EE, v.v.
  • Xác định trình gọi, ví dụ như lớp Java mà bạn thấy từ dấu vết ngăn xếp ngay trước khi gọi Class.forName () hoặc ClassLoader.loadClass (). Điều này sẽ giúp bạn hiểu liệu mã ứng dụng của bạn có bị lỗi hay không so với API của bên thứ ba.
  • Xác định xem mã ứng dụng của bạn không được đóng gói đúng cách, ví dụ như thiếu (các) tệp JAR từ classpath của bạn
  • Nếu lớp Java bị thiếu không phải từ mã ứng dụng của bạn, thì hãy xác định xem nó có thuộc API của bên thứ ba mà bạn đang sử dụng theo ứng dụng Java của mình hay không. Khi bạn xác định được nó, bạn sẽ cần thêm (các) tệp JAR bị thiếu vào classpath thời gian chạy hoặc ứng dụng web của mình WAR/EAR .
  • Nếu vẫn gặp khó khăn sau nhiều lần giải quyết, điều này có thể có nghĩa là vấn đề phân cấp trình tải lớp phức tạp hơn. Trong trường hợp này, vui lòng xem lại NoClassDefFoundError loạt bài viết để biết thêm các ví dụ và chiến lược giải quyết

Trong bài viết này, chúng tôi đã giải thích Cách giải quyết java.lang.ClassNotFoundException
Đừng ngần ngại cho chúng tôi biết nếu bạn có câu hỏi hoặc nhận xét về bài viết này. Để lại bình luận bên dưới và signalfix.net sẽ phản hồi trong thời gian sớm nhất.