如何修复外部 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>
我在主项目的 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,请使用以下命令:
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>