简体   繁体   English

Maven 依赖项上的 NoClassDefFoundError

[英]NoClassDefFoundError on Maven dependency

My first use of Maven and I'm stuck with dependencies.我第一次使用 Maven 并且我被依赖项困住了。

I created a Maven project with Eclipse and added dependencies, and it was working without problems.我用 Eclipse 创建了一个 Maven 项目并添加了依赖项,它运行没有问题。

But when I try to run it via command line:但是当我尝试通过命令行运行它时:

$ 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

It downloads dependencies, successfully builds, but when I try to run it, I get NoClassDefFoundError:它下载依赖项,成功构建,但是当我尝试运行它时,出现 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

My pom.xml is like this:我的 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>

Can anyone help me?谁能帮我?

By default, Maven doesn't bundle dependencies in the JAR file it builds, and you're not providing them on the classpath when you're trying to execute your JAR file at the command-line.默认情况下,Maven 不会在它构建的 JAR 文件中捆绑依赖项,并且当您尝试在命令行执行 JAR 文件时,您不会在类路径上提供它们。 This is why the Java VM can't find the library class files when trying to execute your code.这就是 Java VM 在尝试执行代码时找不到库类文件的原因。

You could manually specify the libraries on the classpath with the -cp parameter, but that quickly becomes tiresome.您可以使用-cp参数手动指定类路径上的库,但这很快就会变得令人厌烦。

A better solution is to "shade" the library code into your output JAR file.更好的解决方案是将库代码“遮蔽”到您的输出 JAR 文件中。 There is a Maven plugin called the maven-shade-plugin to do this.有一个名为maven-shade-pluginMaven 插件可以做到这一点。 You need to register it in your POM, and it will automatically build an "uber-JAR" containing your classes and the classes for your library code too when you run mvn package .您需要在 POM 中注册它,当您运行mvn package时,它会自动构建一个“uber-JAR”,其中包含您的类和库代码的类。

To simply bundle all required libraries, add the following to your POM:要简单地捆绑所有必需的库,请将以下内容添加到您的 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>

Once this is done, you can rerun the commands you used above:完成此操作后,您可以重新运行上面使用的命令:

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

If you want to do further configuration of the shade plugin in terms of what JARs should be included, specifying a Main-Class for an executable JAR file, and so on, see the "Examples" section on the maven-shade-plugin site .如果您想根据应包含哪些 JAR 对 shade 插件进行进一步配置,为可执行 JAR 文件指定 Main-Class 等,请参阅maven-shade-plugin 站点上的“示例”部分。

when I try to run it, I get NoClassDefFoundError当我尝试运行它时,出现 NoClassDefFoundError

Run it how?怎么跑? You're probably trying to run it with eclipse without having correctly imported your maven classpath.您可能试图在没有正确导入 Maven 类路径的情况下使用 Eclipse 运行它。 See the m2eclipse plugin for integrating maven with eclipse for that.请参阅m2eclipse插件以将 maven 与 eclipse 集成。

To verify that your maven config is correct, you could run your app with the exec plugin using:要验证您的 maven 配置是否正确,您可以使用exec 插件运行您的应用程序:

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

Update: First, regarding your error when running exec:java , your main class is tr.edu.hacettepe.cs.b21127113.bil138_4.App .更新:首先,关于运行exec:java时的错误,您的主类是tr.edu.hacettepe.cs.b21127113.bil138_4.App When talking about class names, they're (almost) always dot-separated.在谈论类名时,它们(几乎)总是以点分隔。 The simple class name is just the last part: App in your case.简单的类名只是最后一部分:在您的情况下为App The fully-qualified name is the full package plus the simple class name, and that's what you give to maven or java when you want to run something.完全限定名称是完整的包加上简单的类名,这就是当您想要运行某些东西时提供给 maven 或 java 的名称。 What you were trying to use was a file system path to a source file.您尝试使用的是源文件的文件系统路径。 That's an entirely different beast.那是完全不同的野兽。 A class name generally translates directly to a class file that's found in the class path, as compared to a source file in the file system.与文件系统中的源文件相比,类名通常直接转换为在类路径中找到的类文件。 In your specific case, the class file in question would probably be at target/classes/tr/edu/hacettepe/cs/b21127113/bil138_4/App.class because maven compiles to target/classes , and java traditionally creates a directory for each level of packaging.在您的特定情况下,有问题的类文件可能位于target/classes/tr/edu/hacettepe/cs/b21127113/bil138_4/App.class因为 maven 编译为target/classes ,而 java 传统上为每个级别创建一个目录的包装。

Your original problem is simply that you haven't put the Jackson jars on your class path.你最初的问题只是你没有把杰克逊罐子放在你的班级路径上。 When you run a java program from the command line, you have to set the class path to let it know where it can load classes from.当您从命令行运行 java 程序时,您必须设置类路径以让它知道它可以从哪里加载类。 You've added your own jar, but not the other required ones.您已经添加了自己的 jar,但没有添加其他必需的 jar。 Your comment makes me think you don't understand how to manually build a class path.您的评论让我觉得您不了解如何手动构建类路径。 In short, the class path can have two things: directories containing class files and jars containing class files.简而言之,类路径可以有两个东西:包含类文件的目录和包含类文件的 jar。 Directories containing jars won't work.包含 jar 的目录将不起作用。 For more details on building a class path, see " Setting the class path " and the java and javac tool documentation.有关构建类路径的更多详细信息,请参阅“ 设置类路径”和javajavac工具文档。

Your class path would need to be at least, and without the line feeds:您的类路径至少需要是,并且没有换行符:

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

Note that the separator on Windows is a semicolon (;).请注意,Windows 上的分隔符是分号 (;)。

I apologize for not noticing it sooner.我很抱歉没有早点注意到它。 The problem was sitting there in your original post, but I missed it.问题出在你原来的帖子里,但我错过了。

You have to make classpath in pom file for your dependency.您必须在 pom 文件中为您的依赖项创建类路径。 Therefore you have to copy all the dependencies into one place.因此,您必须将所有依赖项复制到一个地方。

Check my blog . 检查我的博客

<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>

This is due to Morphia jar not being part of your output war/jar.这是因为 Morphia jar 不是您的输出 war/jar 的一部分。 Eclipse or local build includes them as part of classpath, but remote builds or auto/scheduled build don't consider them part of classpath. Eclipse 或本地构建将它们作为类路径的一部分包含在内,但远程构建或自动/计划构建不将它们视为类路径的一部分。

You can include dependent jars using plugin.您可以使用插件包含依赖的 jar。

Add below snippet into your pom's plugins section将以下代码段添加到您的 pom 插件部分

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

For some reason, the lib is present while compiling , but missing while running .出于某种原因,lib在编译时存在,但在运行时丢失

My situation is, two versions of one lib conflict.我的情况是,一个库的两个版本冲突。

For example, A depends on B and C, while B depends on D:1.0, C depends on D:1.1, maven may just import D:1.0.例如,A 依赖于 B 和 C,而 B 依赖于 D:1.0,C 依赖于 D:1.1,maven 可能只是导入 D:1.0。 If A uses one class which is in D:1.1 but not in D:1.0, a NoClassDefFoundError will be throwed.如果 A 使用一个在 D:1.1 但不在 D:1.0 中的类,则会抛出 NoClassDefFoundError。

If you are in this situation too, you need to resolve the dependency conflict.如果您也处于这种情况,则需要解决依赖冲突。

I was able to work around it by running mvn install:install-file with -Dpackaging=class.我可以通过使用 -Dpackaging=class 运行 mvn install:install-file 来解决它。 Then adding entry to POM as described here :如上所述,然后添加条目POM这里

选择 Project -> Clean 应该可以解决这个问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM