ClassNotFoundException 在 eclipse 构建路径(minecraft 插件)中使用另一个 jar 文件时
ClassNotFoundException When using another jar file in eclipse build path (minecraft plugin)
我正在尝试使用我制作的 .JAR 文件作为我当前项目的 API。
This is the GitHub page for the API, and this 是我正在开发的插件的代码。
我收到这些错误:
04.01 17:32:03 [Server] INFO Caused by: java.lang.NoClassDefFoundError: me/Andrew/XenforoAPI/SiteAPI
04.01 17:32:03 [Server] INFO at me.Andrew.BreezeSiteLink.APICaller.postApplication(APICaller.java:16) ~[?:?]
04.01 17:32:03 [Server] INFO at me.Andrew.BreezeSiteLink.Main.onCommand(Main.java:84) ~[?:?]
04.01 17:32:03 [Server] INFO at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot.jar:git-Spigot-5391d73-0ebb9c7]
04.01 17:32:03 [Server] INFO ... 15 more
04.01 17:32:03 [Server] INFO Caused by: java.lang.ClassNotFoundException: me.Andrew.XenforoAPI.SiteAPI
04.01 17:32:03 [Server] INFO at java.net.URLClassLoader.run(URLClassLoader.java:359) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at java.net.URLClassLoader.run(URLClassLoader.java:348) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at java.security.AccessController.doPrivileged(Native Method) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at java.net.URLClassLoader.findClass(URLClassLoader.java:347) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:101) ~[spigot.jar:git-Spigot-5391d73-0ebb9c7]
在 Eclipse 中,选中 "Export as JAR file"(但未选中 "Runnable JAR file")。
我该如何解决这个问题并让 API 与插件一起编译?
右键单击您的项目 -> Java 构建路径 -> 库 -> 添加外部 Jars
然后您可以 select 您想要在项目中使用的 jar / api,但不要忘记将它也添加到 plugin.yml 中的依赖项中:
depend: [Plugin1, Plugin2...]
如前所述,该错误是您的插件未找到您的 API 库的结果。在大多数情况下,我建议您在插件的 JAR 中包含该依赖项。
但是,如果这个 API 本身不是插件,被多个插件使用,请在服务器根目录创建一个 lib
目录并将您的 API JAR 在其中。 位于此目录中的任何 JAR 文件都将由 Bukkit/Spigot 加载并可供所有插件使用。
编辑:
正如我在评论中提到的,我已经使用这种技术很长时间了,我认为它是 Bukkit 的一个特性。唉,不是。
在MANIFEST.MF
中添加类路径
将以下 maven-jar-plugin
配置添加到您的 POM 中,确保任何范围为 compile
的依赖项都将添加到您的插件的类路径中。类路径是相对于插件的位置(plugin
目录),因此 ../lib/
是服务器根目录中的 lib
目录。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifestEntries>
<Built-By>You</Built-By>
</manifestEntries>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>../lib/</classpathPrefix>
</manifest>
</archive>
/configuration>
</plugin>
本质上,这会在您的插件 META-INF/MANIFEST.MF
中创建一个条目,引用您的 API 库,类似于以下内容:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: You
Class-Path: ../lib/my-api.jar
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_73
创建一个Uber-JAR
上述解决方案对我们来说效果很好,它提供了一个单一位置来维护我们的几个 in-house 插件使用的库。再一次,我们 运行 我们自己的服务器。
如果您 long-term 计划发布您的插件供其他人使用,则此解决方案并不理想。虽然它会起作用,但它需要服务器操作员进行额外的工作,除非 API 库的安装是自动的。话又说回来,安装服务器操作员期望的文件以外的文件也可能不是一个好主意。
更好的解决方案是创建一个 uber-JAR,其中包含您的代码和任何独特的依赖项,例如您的 API。它消除了如上例中那样安装 API JAR 的需要。更重要的是,它避免了在发布新版本插件时可能出现的版本不匹配。
将以下 maven-shade-plugin
配置添加到您的 POM,将创建一个 uber-JAR,其中包含您的插件和 API 类 以及单个 JAR 中的接口。该示例假定您的 API 具有 Maven 坐标 me.andy:myapi:1.0
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<filters>
<filter>
<artifact>me.andy:myapi:1.0</artifact>
<includes>
<include>**</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
在 运行 mvn install
之后,您会在 target
目录中找到三个 JAR 文件(文件名明显不同):
original-myplugin-1.0.jar
- 正常创建的原始 JAR。
myplugin-1.0-shaded.jar
- 合并后的 JAR
myplugin-1.0.jar
- 减少依赖的组合 JAR。这是最终的插件 JAR。
您可以验证任何流行的 ZIP 工具中包含的内容。
我正在尝试使用我制作的 .JAR 文件作为我当前项目的 API。 This is the GitHub page for the API, and this 是我正在开发的插件的代码。
我收到这些错误:
04.01 17:32:03 [Server] INFO Caused by: java.lang.NoClassDefFoundError: me/Andrew/XenforoAPI/SiteAPI
04.01 17:32:03 [Server] INFO at me.Andrew.BreezeSiteLink.APICaller.postApplication(APICaller.java:16) ~[?:?]
04.01 17:32:03 [Server] INFO at me.Andrew.BreezeSiteLink.Main.onCommand(Main.java:84) ~[?:?]
04.01 17:32:03 [Server] INFO at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot.jar:git-Spigot-5391d73-0ebb9c7]
04.01 17:32:03 [Server] INFO ... 15 more
04.01 17:32:03 [Server] INFO Caused by: java.lang.ClassNotFoundException: me.Andrew.XenforoAPI.SiteAPI
04.01 17:32:03 [Server] INFO at java.net.URLClassLoader.run(URLClassLoader.java:359) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at java.net.URLClassLoader.run(URLClassLoader.java:348) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at java.security.AccessController.doPrivileged(Native Method) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at java.net.URLClassLoader.findClass(URLClassLoader.java:347) ~[?:1.7.0_121]
04.01 17:32:03 [Server] INFO at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:101) ~[spigot.jar:git-Spigot-5391d73-0ebb9c7]
在 Eclipse 中,选中 "Export as JAR file"(但未选中 "Runnable JAR file")。
我该如何解决这个问题并让 API 与插件一起编译?
右键单击您的项目 -> Java 构建路径 -> 库 -> 添加外部 Jars
然后您可以 select 您想要在项目中使用的 jar / api,但不要忘记将它也添加到 plugin.yml 中的依赖项中:
depend: [Plugin1, Plugin2...]
如前所述,该错误是您的插件未找到您的 API 库的结果。在大多数情况下,我建议您在插件的 JAR 中包含该依赖项。
但是,如果这个 API 本身不是插件,被多个插件使用,请在服务器根目录创建一个 lib
目录并将您的 API JAR 在其中。 位于此目录中的任何 JAR 文件都将由 Bukkit/Spigot 加载并可供所有插件使用。
编辑:
正如我在评论中提到的,我已经使用这种技术很长时间了,我认为它是 Bukkit 的一个特性。唉,不是。
在MANIFEST.MF
中添加类路径将以下 maven-jar-plugin
配置添加到您的 POM 中,确保任何范围为 compile
的依赖项都将添加到您的插件的类路径中。类路径是相对于插件的位置(plugin
目录),因此 ../lib/
是服务器根目录中的 lib
目录。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifestEntries>
<Built-By>You</Built-By>
</manifestEntries>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>../lib/</classpathPrefix>
</manifest>
</archive>
/configuration>
</plugin>
本质上,这会在您的插件 META-INF/MANIFEST.MF
中创建一个条目,引用您的 API 库,类似于以下内容:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: You
Class-Path: ../lib/my-api.jar
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_73
创建一个Uber-JAR
上述解决方案对我们来说效果很好,它提供了一个单一位置来维护我们的几个 in-house 插件使用的库。再一次,我们 运行 我们自己的服务器。
如果您 long-term 计划发布您的插件供其他人使用,则此解决方案并不理想。虽然它会起作用,但它需要服务器操作员进行额外的工作,除非 API 库的安装是自动的。话又说回来,安装服务器操作员期望的文件以外的文件也可能不是一个好主意。
更好的解决方案是创建一个 uber-JAR,其中包含您的代码和任何独特的依赖项,例如您的 API。它消除了如上例中那样安装 API JAR 的需要。更重要的是,它避免了在发布新版本插件时可能出现的版本不匹配。
将以下 maven-shade-plugin
配置添加到您的 POM,将创建一个 uber-JAR,其中包含您的插件和 API 类 以及单个 JAR 中的接口。该示例假定您的 API 具有 Maven 坐标 me.andy:myapi:1.0
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<filters>
<filter>
<artifact>me.andy:myapi:1.0</artifact>
<includes>
<include>**</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
在 运行 mvn install
之后,您会在 target
目录中找到三个 JAR 文件(文件名明显不同):
original-myplugin-1.0.jar
- 正常创建的原始 JAR。myplugin-1.0-shaded.jar
- 合并后的 JARmyplugin-1.0.jar
- 减少依赖的组合 JAR。这是最终的插件 JAR。
您可以验证任何流行的 ZIP 工具中包含的内容。