如何修复外部 JAR 类 的 NoClassDefFoundError?

How to fix NoClassDefFoundError for external JAR's Classes?

我在主项目的 pom.jar 中添加了自己的外部 jar。它是;

    <dependency>
        <groupId>com.company</groupId>
        <artifactId>antlr-plsql</artifactId>
        <scope>system</scope>
        <version>1.0</version>
        <systemPath>${project.basedir}\lib\antlr-plsql-1.0.0.jar</systemPath>
    </dependency>

当我 运行 在 eclipse 上时,该项目正在运行。但是当我用 maven 得到 jar 时(参数:clean install -DskipTests)。我收到一个错误;

java.lang.NoClassDefFoundError: company/antlr/core/SimplePlsqlListener
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access0(URLClassLoader.java:74)
    at java.net.URLClassLoader.run(URLClassLoader.java:369)
    at java.net.URLClassLoader.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:92)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

这个 Class 来自我的外部 jar。外部jar有什么问题?

当您的 jar 无法在 class 路径中找到依赖项 jar 时,会导致 NoClassDefFoundError。默认情况下,Maven 在构建输出 jar 时不会在 JAR 文件中捆绑依赖项,出于同样的原因,当您尝试从命令行。

这就是 JVM 在尝试执行您的代码时找不到库 class 文件的原因。

您可以使用 -cp 参数在 class 路径上手动指定库,但这很快就会让人厌烦。

更好的解决方案是将库代码“隐藏”(包含)到输出 JAR 文件中。有一个名为 maven-shade-plugin 的 Maven 插件可以执行此操作。您需要在 POM 中注册它,它会自动构建一个“uber-JAR”,也称为 FAT jar,其中包含您的 classes 和库代码的 classes 以及当您 运行 mvn package 命令.

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

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <configuration>
          <!-- put your configurations here -->
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

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

$ mvn package

您可以找到有关 maven-shade-plugin 的更多详细信息 here

此外,您可以让 maven 为您处理,而不是直接从其位置引用外部 jar。 Maven 允许您使用 mvn install:install-file

安装第三方 jar

要在本地存储库中安装 JAR,请使用以下命令:

mvn install:install-file -Dfile=<path-to-file> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=<packaging>

如果还有 pom 文件,您可以使用以下命令安装它:

mvn install:install-file -Dfile=<path-to-file> -DpomFile=<path-to-pomfile>

使用 2.5 版的 maven-install-plugin,它可以变得更简单:如果 JAR 是由 Apache Maven 构建的,它将在 META-INF/ 的子文件夹中包含一个 pom.xml目录,默认情况下将读取该目录。在这种情况下,您需要做的就是:

mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -Dfile=<path-to-file>

这对我有用;首先 运行 这个命令:

mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -Dfile=<path-to-file>

之后,将 pom.xml 依赖项更改为:

    <dependency>
        <groupId>com.company</groupId>
        <artifactId>antlr-plsql</artifactId>
        <scope>compile</scope>
        <version>1.0</version>
    </dependency>