java.lang.NoClassDefFoundError: Không thể khởi tạo lớp XXX


165
public class PropHolder {
  public static Properties prop;

  static {
    //code for loading properties from file
  }
}

// Referencing the class somewhere else:
Properties prop = PropHolder.prop;

class PropHolderlà một lớp học của riêng tôi. Lớp nằm trong cùng tệp JAR của lớp chính. Vì vậy, điều đó không nên bởi vì bất kỳ JAR nào bị thiếu trong classpath.

Khi tôi tìm đến tệp JAR jar tf myjarfile, tôi có thể thấy PropHolder.classdanh sách đó được liệt kê ở đó.

Btw: mã đang chạy tốt trên máy cục bộ của tôi. Nhưng không thể hoạt động khi tôi triển khai nó với một số tập lệnh lên máy chủ Linux. Vì vậy, tôi nghĩ rằng nó không phải là vấn đề của mã. Nhưng vì lý do nào đó. quá trình triển khai là rất khó để theo dõi.

Điều gì có thể là vấn đề?


Là cấu trúc thư mục thích hợp trong jar của bạn để phù hợp với gói lớp?
John B

cần phải xem một số nguồn, nhiều thứ có thể gây ra điều này. ví dụ: câu lệnh 'gói' nhưng tệp không thực sự nằm trong đường dẫn tương ứng
jcomeau_ictx

3
Một nguyên nhân là một ngoại lệ trong quá trình khởi tạo - có bất kỳ đầu ra lỗi nào khác không?
Michael Brewer-Davis

Câu trả lời:


210

Đặt cược tốt nhất của tôi là có một vấn đề ở đây:

static {
    //code for loading properties from file
}

Nó sẽ xuất hiện một số ngoại lệ chưa được phát hiện và được truyền tới ClassLoader thực tế khi cố gắng tải lớp. Chúng tôi sẽ cần một stacktrace để xác nhận điều này mặc dù.

Hoặc đó hoặc nó xảy ra khi tạo PropHolder.propbiến tĩnh.


Tôi đã phải đối mặt với cùng một vấn đề nhiều lần. Tôi chắc chắn rằng đó là vì staticvấn đề. Cần phải làm gì để giải quyết vấn đề?
viper

1
Bạn sẽ cần xác định ngoại lệ nào đang được ném ra khỏi statickhối. Để gỡ lỗi, nó đặt try/catch(Exception e)xung quanh toàn bộ khối và ghi lại ngoại lệ. Bạn sẽ phải sửa ngoại lệ đó. Thông thường, ngoại lệ sẽ được ghi lại nhưng có thể khó tìm thấy vì nó được ghi lại trong quá trình tải lớp có thể xảy ra rất sớm
John Vint

Có tôi giữ mã trong try catchkhối và nó nói Failed to initialize ClassA. Tôi nghĩ đó là vấn đề của JVM. Tôi khởi động lại hệ thống của mình và sau đó mọi thứ hoạt động tốt. Làm thế nào để tôi giải quyết vấn đề này trong tương lai mà không cần khởi động lại hệ thống của mình và giải quyết vấn đề bằng một solu4tion đơn giản.
viper

Không thể khởi tạo ClassA là tác dụng phụ từ thứ khác. Bạn sẽ muốn xem xét causenếu có sẵn. A NoClassDefFoundErrorluôn có liên quan đến một lỗi khác, bạn sẽ cần tìm nó trong nhật ký hoặc cố gắng ghi nhật ký một cách thích hợp hơn (như buộc đăng nhập vào một tệp mới trên hệ thống tệp)
John Vint

Sẽ dễ dàng theo dõi hơn nếu Java sẽ phát sinh lỗi CanNotInitializeStaticPartOfClassError hoặc một cái gì đó. Sau đó, chúng tôi là nhà phát triển sẽ biết nơi để tìm.
Maarten

126

Bạn đang nhận được một java.lang.NoClassDefFoundErrorđiều KHÔNG có nghĩa là lớp của bạn bị thiếu (trong trường hợp đó bạn sẽ nhận được một java.lang.ClassNotFoundException). ClassLoader gặp lỗi trong khi đọc định nghĩa lớp khi cố đọc lớp.

Đặt một thử / bắt bên trong trình khởi tạo tĩnh của bạn và xem xét ngoại lệ. Nếu bạn đọc một số tệp ở đó và nó khác với môi trường cục bộ của bạn thì rất có thể nguyên nhân của sự cố (có thể không tìm thấy tệp, không có quyền, v.v.).


1
Một điều rõ ràng là mặc dù NoClassDefFoundError không ngụ ý ClassNotFoundException, nó vẫn là một nguyên nhân có thể của NoClassDefFoundError.
John Vint

1
buf nếu bạn đã có ClassNotFoundException thì ClassLoader sẽ / không bao giờ có thể thử tải lớp, phải không?
jeha

4
Một lớp có thể đang tải một lớp khác không được tìm thấy. Nguyên nhân trong trường hợp đó vẫn là ClassNotFoundException
John Vint

1
Tôi nên làm rõ, tôi chỉ có nghĩa là một ngoại lệ. Quên đi ()
John Vint

1
Điều này thực sự hữu ích ở đây, vì tôi đã dành khoảng 20 phút để xác minh JAR (lớp báo cáo thuộc về) được bao gồm. Khi tôi nhận ra mình đang nhìn sai hướng, tôi dễ dàng hiểu rằng có khả năng một số lớp chú thích bị thiếu và voila, lớp báo cáo đã được khai báo @Stateless, vì vậy tôi chỉ cần thêm phụ thuộc tương ứng và có thể tiếp tục. Cảm ơn vì tiền hỗ trợ!
RAM237

33

NoClassDefFoundError không đưa ra nhiều manh mối về những gì đã xảy ra trong khối tĩnh. Đó là một thực hành tốt để luôn có một khối như thế này bên trong mã khởi tạo {...} tĩnh:

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}

Làm thế nào để làm điều này trong kotlin?
Marlon

Cảm ơn đã cho gợi ý. Trong trường hợp của tôi, tôi đã nhận được NPE khi khởi tạo dòng tĩnh.
Abhishek

3

Tôi cũng có ngoại lệ tương tự, đây là cách tôi giải quyết vấn đề:

Điều kiện tiên quyết:

  1. Lớp Junit (và kiểm tra), đã mở rộng một lớp khác.

  2. ApplicationContext khởi tạo bằng spring, khởi tạo dự án.

  3. Bối cảnh ứng dụng đã được khởi tạo trong phương thức @B Before

Giải pháp:

Khởi tạo bối cảnh ứng dụng từ phương thức @B BeforeClass, vì lớp cha cũng yêu cầu một số lớp được khởi tạo từ trong ngữ cảnh ứng dụng.

Hy vọng điều này sẽ giúp.


2

Như đã đề cập ở trên, đây có thể là một số điều. Trong trường hợp của tôi, tôi đã có một biến khởi tạo tĩnh dựa trên một mục bị thiếu trong tệp thuộc tính của tôi. Đã thêm mục bị thiếu vào tệp thuộc tính và vấn đề đã được giải quyết.


1

Chỉ vài ngày trước, tôi đã gặp câu hỏi tương tự như của bạn. Tất cả các mã chạy tốt trên máy cục bộ của tôi, nhưng hóa ra lỗi (noclassdeffound & khởi tạo). Vì vậy, tôi đăng giải pháp của mình, nhưng tôi không biết tại sao, tôi chỉ đưa ra một khả năng. Tôi hy vọng ai đó biết sẽ giải thích điều này. @ John Vint Trước tiên, tôi sẽ chỉ cho bạn vấn đề của tôi. Mã của tôi có biến tĩnh và khối tĩnh cả. Khi tôi gặp vấn đề này lần đầu tiên, tôi đã thử giải pháp của John Vint và cố gắng bắt ngoại lệ. Tuy nhiên, tôi không bắt được gì. Vì vậy, tôi nghĩ rằng đó là vì biến tĩnh (nhưng bây giờ tôi biết chúng là cùng một thứ) và vẫn không tìm thấy gì. Vì vậy, tôi cố gắng tìm sự khác biệt giữa máy linux và máy tính của tôi. Sau đó, tôi thấy rằng vấn đề này chỉ xảy ra khi một số luồng chạy trong một tiến trình (Nhân tiện, máy linux có lõi kép và tiến trình kép). Điều đó có nghĩa là nếu có hai tác vụ (cả hai đều sử dụng mã có khối tĩnh hoặc biến) chạy trong cùng một quy trình thì sẽ bị lỗi, nhưng nếu chúng chạy trong các quy trình khác nhau thì cả hai đều ổn. Trong máy Linux, tôi sử dụng

mvn -U clean  test -Dtest=path 

để chạy một tác vụ và bởi vì biến tĩnh của tôi là khởi động một thùng chứa (hoặc có thể bạn khởi tạo một trình nạp lớp mới), vì vậy nó sẽ duy trì cho đến khi jvm dừng và jvm chỉ dừng khi tất cả các tác vụ trong một tiến trình dừng lại. Mỗi tác vụ sẽ bắt đầu một container mới (hoặc trình nạp lớp) và nó làm cho jvm bối rối. Hậu quả là lỗi xảy ra. Vậy, làm thế nào để giải quyết nó? Giải pháp của tôi là thêm một lệnh mới vào lệnh maven và làm cho mọi tác vụ đi đến cùng một thùng chứa.

-Dxxx.version=xxxxx #sorry can't post more

Có thể bạn đã giải quyết vấn đề này, nhưng vẫn hy vọng nó sẽ giúp những người khác gặp vấn đề tương tự.


Hơn nữa, khi mã chạy trên máy linux, xảy ra lỗi ở trên, có một vấn đề khác : java.lang.ExceptionInInitializerError: null, điều đó có nghĩa là không thể tìm thấy lớp trong trình nạp lớp hoặc không biết tải cái nào (tôi đoán). Bạn đã gặp điều đó?
MonkeyKing

1

Tôi cũng có ngoại lệ tương tự - nhưng chỉ khi chạy trong chế độ gỡ lỗi, đây là cách tôi giải quyết vấn đề (sau 3 ngày): trong bản build.gradle tôi đã có: "multiDexEnabled true" được đặt trong phần defaultConfig.

        defaultConfig {
    applicationId "com.xxx.yyy"
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 5123
    versionName "5123"
    // Enabling multidex support.
    multiDexEnabled true
}

nhưng dường như điều này là không đủ. nhưng khi tôi thay đổi:

public class MyAppClass  extends Application 

đến:

public class MyAppClass  extends MultiDexApplication 

Điều này đã giải quyết nó. hy vọng điều này sẽ giúp được ai đó


0

Nếu bạn đang làm việc trên một dự án Android, hãy đảm bảo rằng bạn không gọi bất kỳ phương thức tĩnh nào trên bất kỳ lớp Android nào. Tôi chỉ sử dụng JUnit + Mockito, vì vậy có thể một số khung công tác khác có thể giúp bạn tránh vấn đề hoàn toàn, tôi không chắc chắn.

Vấn đề của tôi là gọi Uri.parse(uriString)như một phần của trình khởi tạo tĩnh cho một bài kiểm tra đơn vị. Lớp Uri là API Android, đó là lý do tại sao bản dựng thử nghiệm đơn vị không thể tìm thấy nó. Tôi đã thay đổi giá trị này để nullthay thế và mọi thứ trở lại bình thường.


0

Tôi gặp vấn đề tương tự, java java.lang.NoClassDefFoundError: Không thể khởi tạo lớp com.xxx.HttpUtils

static {
    //code for loading properties from file
}

đó là vấn đề môi trường. Điều đó có nghĩa là các thuộc tính trong application.yml không chính xác hoặc trống!


0

Tôi gặp vấn đề tương tự. Tôi đã kích hoạt một đối tượng bean trong khối tĩnh như dưới đây:

static {
    try{
        mqttConfiguration = SpringBootBeanUtils.<MqttConfiguration>getBean(MqttConfiguration.class);
    }catch (Throwable e){
        System.out.println(e);
    }
 }

Chỉ vì quá trình khởi động đậu của tôi gây ra NPE, tôi gặp rắc rối với nó. Vì vậy, tôi nghĩ rằng bạn nên kiểm tra bạn khối mã tĩnh cẩn thận.

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.