关于Maven依赖的NoClassDefFoundError


73

我第一次使用Maven时,就陷入了依赖关系。

我使用Eclipse创建了一个Maven项目并添加了依赖项,并且该项目运行正常。

但是当我尝试通过命令行运行它时:

$ mvn package  # successfully completes
$ java -cp target/bil138_4-0.0.1-SNAPSHOT.jar tr.edu.hacettepe.cs.b21127113.bil138_4.App # NoClassDefFoundError for dependencies

它下载依赖项,成功构建,但是当我尝试运行它时,出现NoClassDefFoundError:

Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/jackson/JsonParseException
        at tr.edu.hacettepe.cs.b21127113.bil138_4.db.DatabaseManager.<init>(DatabaseManager.java:16)
        at tr.edu.hacettepe.cs.b21127113.bil138_4.db.DatabaseManager.<init>(DatabaseManager.java:22)
        at tr.edu.hacettepe.cs.b21127113.bil138_4.App.main(App.java:10)
Caused by: java.lang.ClassNotFoundException: org.codehaus.jackson.JsonParseException
        at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
        ... 3 more

我的pom.xml是这样的:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>tr.edu.hacettepe.cs.b21127113</groupId>
  <artifactId>bil138_4</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>bil138_4</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>        
    <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>           
    </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>             
        </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>1.9.6</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.6</version>
    </dependency>
    </dependencies>
  </dependencyManagement>
</project>

谁能帮我?


我遇到了同样的问题,我在主类中忘记了com.myapp.mypack.myclass软件包。添加它解决了我的问题。

Answers:


23

当我尝试运行它时,出现NoClassDefFoundError

运行方式如何?您可能正在尝试使用Eclipse运行它,而没有正确导入您的Maven类路径。请参阅m2eclipse插件,以将maven与eclipse集成。

要验证您的maven配置是否正确,可以使用exec插件运行您的应用程序,方法是:

mvn exec:java -D exec.mainClass=<your main class>

更新:首先,关于运行时的错误exec:java,您的主类为tr.edu.hacettepe.cs.b21127113.bil138_4.App。在谈论类名时,它们(几乎)总是用点分隔。简单的类名只是最后一部分:App就您而言。完全限定的名称是完整的程序包加上简单的类名称,这就是您要运行某些东西时给maven或java的名称。您尝试使用的是源文件的文件系统路径。那是完全不同的野兽。与文件系统中的源文件相比,类名通常直接转换为在类路径中找到的类文件。在您的特定情况下,有问题的类文件可能位于,target/classes/tr/edu/hacettepe/cs/b21127113/bil138_4/App.class因为maven编译为target/classes,并且Java传统上为每个包装级别创建一个目录。

您最初的问题仅仅是因为您没有将Jackson罐子放在课堂上。从命令行运行Java程序时,必须设置类路径以使其知道从何处可以加载类。您已添加了自己的jar,但未添加其他必需的jar。您的评论使我认为您不了解如何手动构建类路径。简而言之,类路径可以有两件事:包含类文件的目录和包含类文件的jar。包含jar的目录将不起作用。有关构建类路径的更多详细信息,请参见“设置类路径”以及javajavac工具文档。

您的课程路径必须至少是,并且没有换行符:

target/bil138_4-0.0.1-SNAPSHOT.jar:
/home/utdemir/.m2/repository/org/codehaus/jackson/jackson-core-asl/1.9.6/jackson-core-asl-1.9.6.jar:
/home/utdemir/.m2/repository/org/codehaus/jackson/jackson-mapper-asl/1.9.6/jackson-mapper-asl-1.9.6.jar

请注意,Windows上的分隔符是分号(;)。

我很抱歉没有及时注意到。问题出在你原来的帖子里,但是我错过了。


收到此错误:pastebin.com/g2txkMY6。我可以使用m2eclipse插件在eclipse上运行它,我在上面开发了应用程序。我不能仅仅弄清楚如何通过命令行运行它。以及如何导入我的Maven类路径?编辑:尝试向Java命令添加-classpath /home/utdemir/.m2/repository/参数,仍然没有运气。
utdemir 2012年

谢谢。如您所说设置类路径可以解决问题,将问题标记为已解决。但是我还有几个问题:1-为什么我不必为Jackson插件添加Jackson到classpath中?2- Exec插件需要编译我的项目,所以我应该运行mvn compile或package,对吗?3-这段代码是我的工作,是否应将库添加到类路径中是他们的责任,还是我必须对此做些什么?
utdemir

2
1)您通过maven运行的几乎所有东西(包括exec插件)都将根据pom中指定的项目依赖关系自动为您设置类路径。这是Maven受欢迎的主要原因。2)是的,您必须至少mvn compile在运行exec插件之前运行。3)最后,如果我要提交作业,请确保它可以以指定的任何方式完全执行。如果您对如何打包项目或上交项目有疑问,建议您提出一个新的SO问题。
瑞安·斯图尔特

插件链接无效。
卡梅隆·哈德森

130

默认情况下,Maven不会在生成的JAR文件中捆绑依赖项,并且在尝试通过命令行执行JAR文件时,不会在类路径中提供依赖项。这就是为什么Java VM在尝试执行代码时找不到库类文件的原因。

您可以使用手动在类路径上指定库 -cp参数,但这很快就变得很麻烦。

更好的解决方案是将库代码“着色”到输出JAR文件中。有一个名为maven-shade-pluginMaven插件可以执行此操作。您需要在POM中注册它,它会在运行时自动构建一个包含您的类和库代码类的“ uber-JAR”mvn package

要简单地捆绑所有必需的库,请将以下内容添加到您的POM中:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

完成此操作后,您可以重新运行上面使用的命令:

$ mvn package
$ java -cp target/bil138_4-0.0.1-SNAPSHOT.jar tr.edu.hacettepe.cs.b21127113.bil138_4.App

如果要根据应包括的JAR进行进一步的shade插件配置,为可执行的JAR文件指定Main-Class,等等,请参见maven-shade-plugin站点上的“示例”部分。


5
万一有人遇到这个问题,可以在这里获得插件的实际版本,因为1.6现在已经很老了:mvnrepository.com/artifact/org.apache.maven.plugins/…–
Scadge

唯一的区别不是<version> 3.1.1 </ version>(而不是1.6)吗?运行“ mvn软件包”似乎会自动下载maven-shade
user3211306 '18

我的团队碰巧使用<groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId>使用<goals><goal>copy-dependencies</goal></goals>
安德鲁·基尔纳

4

您必须在pom文件中创建classpath以获取依赖关系。因此,您必须将所有依赖项复制到一个地方。

检查我的博客

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>2.1</version>
      <executions>
        <execution>
          <id>copy-dependencies</id>
          <phase>package</phase>
          <goals>
            <goal>copy-dependencies</goal>
          </goals>
          <configuration>
            <outputDirectory>${project.build.directory}/lib</outputDirectory>
            <overWriteReleases>false</overWriteReleases>
            <overWriteSnapshots>false</overWriteSnapshots>
            <overWriteIfNewer>true</overWriteIfNewer>
          </configuration>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <version>2.4</version>
      <configuration>
        <archive>
          <manifest>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
            <mainClass>$fullqualified path to your main Class</mainClass>
          </manifest>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

3

这是由于Morphia jar不属于您的输出war / jar。Eclipse或本地构建将它们作为类路径的一部分包括在内,但是远程构建或自动/计划的构建不将它们视为类路径的一部分。

您可以使用插件包含相关的jar。

将以下代码段添加到pom的插件部分

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
        </configuration>
    </plugin>

0

由于某种原因,lib在编译时存在,但在运行时丢失

我的情况是,一个库冲突的两个版本。

例如,A依赖于B和C,而B依赖于D:1.0,C依赖于D:1.1,maven可能仅导入D:1.0。如果A使用一个在D:1.1中但不在D:1.0中的类,则将引发NoClassDefFoundError。

如果您也处于这种情况下,则需要解决依赖性冲突。


2
对于这个有助于提问者的答案,如果您已经解释了如何解决所涉及的冲突类型,那可能会有所帮助。
Dragonthoughts

-1

我可以通过使用-Dpackaging = class运行mvn install:install-file来解决此问题。如上所述,然后添加条目POM这里


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.