Maven 阴影可执行 uber jar NoClassDefFoundError
Maven shade executable uber jar NoClassDefFoundError
我正在使用 maven shade 插件创建一个可执行的 uber jar,它依赖于我想要的本地系统 jar (mobile-dock-support.jar) 中的某些 类在打包阶段包含,所以我有像这样配置的阴影插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>uk.xxx.mobiledock.PCSyncApplication</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.build.directory}/../src/main/libs/mobile-dock-support.jar</systemPath>
</dependency>
</dependencies>
</plugin>
它似乎很好地打包了罐子,但是当我 运行 使用 java -jar xxx.jar
罐子时,它给了我以下内容
java.lang.NoClassDefFoundError: uk/xxx/mobiledock/MobileDockException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: uk.xxx.mobiledock.MobileDockException
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 7 more
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main"
我还设置了 exec maven 插件,运行正在 mvn exec:java -Dexec.mainClass=uk.xxx.mobiledock.PCSyncApplication
运行 按预期设置程序。
这里是 exec maven 插件的设置方式
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>uk.xxx.mobiledock.PCSyncApplication</mainClass>
</configuration>
<dependencies>
<dependency>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.build.directory}/../src/main/libs/mobile-dock-support.jar</systemPath>
</dependency>
</dependencies>
</plugin>
好的,看来问题是 shade 插件没有将系统依赖项复制到 uber jar。有几种 'correct' 方法可以解决这个问题
使用 mvn install
将依赖项安装到本地 Maven 存储库
使用存储库管理器,例如 Nexus
但是如果你像我一样没有以上两个选项,因为它是一个协作项目,并且没有像 Nexus 这样的选项,那么我就是这样做的
使用 maven 依赖插件将任何系统依赖项复制到相对于打包的 jar 的某个位置,例如。
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<includeArtifactIds>mobile-dock-support</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
将复制的 jar 作为 class 路径的一部分添加到 uber jar 的清单文件中,例如
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>uk.xxx.mobiledock.PCSyncApplication</Main-Class>
<Class-Path>lib/mobile-dock-support-${mobile-dock-support.version}.jar</Class-Path>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
我正在使用 maven shade 插件创建一个可执行的 uber jar,它依赖于我想要的本地系统 jar (mobile-dock-support.jar) 中的某些 类在打包阶段包含,所以我有像这样配置的阴影插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>uk.xxx.mobiledock.PCSyncApplication</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.build.directory}/../src/main/libs/mobile-dock-support.jar</systemPath>
</dependency>
</dependencies>
</plugin>
它似乎很好地打包了罐子,但是当我 运行 使用 java -jar xxx.jar
罐子时,它给了我以下内容
java.lang.NoClassDefFoundError: uk/xxx/mobiledock/MobileDockException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: uk.xxx.mobiledock.MobileDockException
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 7 more
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main"
我还设置了 exec maven 插件,运行正在 mvn exec:java -Dexec.mainClass=uk.xxx.mobiledock.PCSyncApplication
运行 按预期设置程序。
这里是 exec maven 插件的设置方式
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>uk.xxx.mobiledock.PCSyncApplication</mainClass>
</configuration>
<dependencies>
<dependency>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.build.directory}/../src/main/libs/mobile-dock-support.jar</systemPath>
</dependency>
</dependencies>
</plugin>
好的,看来问题是 shade 插件没有将系统依赖项复制到 uber jar。有几种 'correct' 方法可以解决这个问题
使用
mvn install
将依赖项安装到本地 Maven 存储库
使用存储库管理器,例如 Nexus
但是如果你像我一样没有以上两个选项,因为它是一个协作项目,并且没有像 Nexus 这样的选项,那么我就是这样做的
使用 maven 依赖插件将任何系统依赖项复制到相对于打包的 jar 的某个位置,例如。
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<includeArtifactIds>mobile-dock-support</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
将复制的 jar 作为 class 路径的一部分添加到 uber jar 的清单文件中,例如
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>uk.xxx.mobiledock.PCSyncApplication</Main-Class>
<Class-Path>lib/mobile-dock-support-${mobile-dock-support.version}.jar</Class-Path>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>