java.lang.NoClassDefFoundError:无法初始化类XXX


164
public class PropHolder {
  public static Properties prop;

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

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

class PropHolder是我自己的一类。该类与主类位于同一JAR文件中。因此,这不应该是因为classpath中缺少任何JAR。

当我通过查找到JAR文件时jar tf myjarfile,可以看到其中PropHolder.class列出的内容。

顺便说一句:代码在我的本地计算机上运行良好。但是当我将其与某些脚本一起部署到Linux服务器上时无法工作。所以我认为这不是代码的问题。但是出于某种原因。部署过程很难跟踪。

可能是什么问题呢?


jar中是否有合适的目录结构来匹配类包?
约翰·B

需要查看一些源,很多事情都可能导致此。例如,“ package”语句,但文件实际上不在相应路径中
jcomeau_ictx 2011年

3
原因是初始化期间发生异常-是否还有其他错误输出?
Michael Brewer-Davis

Answers:


209

我最好的选择是这里有一个问题:

static {
    //code for loading properties from file
}

可能会出现一些未捕获的异常,并传播到尝试加载该类的实际ClassLoader。我们将需要一个堆栈跟踪来确认这一点。

创建PropHolder.prop静态变量时发生了这种情况。


我一次又一次面对同样的问题。我敢肯定是因为这个static问题。解决问题需要做些什么?
毒蛇

1
您将需要确定从该static块引发了什么异常。要对其进行调试,请try/catch(Exception e)在整个块中放一个并记录异常。您必须修复该异常。通常,该异常将被记录,但可能很难找到,因为它是在类加载期间记录的,这可能发生得很早
John Vint

是的,我把代码放在了try catch块里,它说了Failed to initialize ClassA。我认为这是问题JVM。我重新启动系统,然后一切正常。将来如何解决此问题而不重启系统,并通过简单的解决方案解决问题。
毒蛇

无法初始化ClassA是其他原因的副作用。您将要查看cause如果可用。A NoClassDefFoundError总是与另一个错误相关联,您将需要在日志中查找它或尝试更适当地记录它(例如强制将其记录到文件系统上的新文件中)
John Vint

如果Java抛出错误CouldNotInitializeStaticPartOfClassError或其他内容,则将更易于跟踪。然后,作为开发人员,我们将知道在哪里看。
马滕

125

您得到的a java.lang.NoClassDefFoundError并不表示您的课程缺失(在这种情况下,您将获得java.lang.ClassNotFoundException)。尝试读取类时,在读取类定义时,ClassLoader遇到错误。

将try / catch放入静态初始值设定项中,然后查看异常。如果您在此处读取某些文件,并且它与您的本地环境不同,则很可能是造成问题的原因(也许找不到文件,没有权限等)。


1
一项澄清是,即使NoClassDefFoundError并不暗示ClassNotFoundException,它仍然可能是NoClassDefFoundError的原因。
John Vint

1
buf如果您有ClassNotFoundException,则ClassLoader将/永远不会尝试加载类,对吗?
杰哈

4
一个类可能正在加载另一个未找到的类。在这种情况下,原因仍然是ClassNotFoundException
John Vint

1
我应该澄清一下,我只是想说一个exception.getCause()
John Vint

1
这对我真的很有帮助,因为我花了大约20分钟的时间来验证是否包含JAR(报告的类属于)。一旦意识到自己进入了错误的方向,我就很容易理解,可能缺少某些注释类,瞧瞧,报告的那个被声明为@Stateless,所以我只需添加相应的依赖项就可以继续进行下去。谢谢你的提示!
RAM237

33

NoClassDefFoundError没有提供太多关于静态块内部发生错误的线索。最好在静态{...}初始化代码中始终包含这样的块:

static {
  try {

    ... your init code here

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

如何在Kotlin中做到这一点?
马龙

感谢您的提示。就我而言,我在静态线路初始化上得到了NPE。
阿比舍克

3

我有同样的例外,这就是我解决问题的方式:

前提条件:

  1. Junit类(和测试),扩展了另一个类。

  2. 使用Spring初始化的ApplicationContext会初始化项目。

  3. 在@Before方法中初始化了Application上下文

解:

从@BeforeClass方法初始化应用程序上下文,因为父类也需要一些从应用程序上下文中初始化的类。

希望这会有所帮助。


2

如上所述,这可能是很多事情。就我而言,我有一个静态初始化的变量,该变量依赖于属性文件中的缺失条目。将缺少的条目添加到属性文件中,问题已解决。


1

就在几天前,我遇到了和您一样的相同问题。所有代码在我的本地计算机上运行都很好,但是结果出错(noclassdeffound&initialize)。所以我发布了解决方案,但我不知道为什么,我只是提出了一种可能性。我希望有人能对此做出解释。@ John Vint首先,我将向您展示我的问题。我的代码同时具有静态变量和静态块。当我第一次遇到这个问题时,我尝试了John Vint的解决方案,并试图捕获异常。但是,我什么也没发现。所以我认为这是因为静态变量(但现在我知道它们是同一件事),但仍然没有发现任何东西。因此,我尝试找出linux机器和我的计算机之间的区别。然后我发现只有在一个进程中运行多个线程时才会发生此问题(顺便说一句,Linux计算机具有双核和双进程)。这意味着如果有两个任务(都使用具有静态块或变量的代码)在同一进程中运行,则会出错,但如果它们在不同的进程中运行,则两者都可以。在Linux机器上,我使用

mvn -U clean  test -Dtest=path 

运行一个任务,并且因为我的静态变量是启动一个容器(或者您初始化一个新的类加载器),所以它将一直保持到jvm停止,并且jvm仅在一个进程中的所有任务停止时才停止。每个任务都会启动一个新的容器(或类加载器),并使jvm感到困惑。结果,发生错误。那么,如何解决呢?我的解决方案是在maven命令中添加一个新命令,并使每个任务进入同一容器。

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

也许您已经解决了这个问题,但是仍然希望它可以帮助遇到同样问题的其他人。


而且,当代码在linux机器上运行时,遵循上面的错误,还有另一个问题:java.lang.ExceptionInInitializerError: null,这意味着无法在类加载器中找到该类,或者不知道加载哪个(我猜)。你遇到了吗?
MonkeyKing

1

我有同样的例外-但只有在以调试模式运行时,这才是我解决问题的方式(整整3天后):在build.gradle中,我在defaultConfig部分中设置了“ multiDexEnabled true”。

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

但是显然这还不够。但是当我改变时:

public class MyAppClass  extends Application 

至:

public class MyAppClass  extends MultiDexApplication 

这解决了。希望这会帮助某人


0

如果您正在处理Android项目,请确保未在任何Android类上调用任何静态方法。我仅使用JUnit + Mockito,所以不确定,也许其他一些框架可能会帮助您完全避免该问题。

我的问题是Uri.parse(uriString)作为单元测试的静态初始化程序的一部分进行调用。Uri类是一个Android API,这就是为什么单元测试版本找不到它的原因。我将此值null改为,一切恢复正常。


0

我遇到了同样的问题:java.lang.NoClassDefFoundError:无法初始化com.xxx.HttpUtils类

static {
    //code for loading properties from file
}

这是环境问题。这意味着application.yml中的属性不正确或为空!


0

我遇到同样的问题。我在静态块中初始化了一个bean对象,如下所示:

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

仅仅是因为我的bean对象的创建过程导致了NPE,所以我遇到了麻烦。因此,我认为您应该仔细检查静态代码块。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.