首先,我想说我不想使用Maven,Ant,Gradle,任何IDE或类似的任务。
我想使用bash脚本制作一个可运行的jar。 jar应该包含来自我" libs"的所有jar内容。文件夹中。
我已经开始使用这个脚本而且它已经差不多了#34;有效(直到jar创作):
#!/bin/bash
#Setup
libs=$(find libs -name "*.jar" -print0 | xargs -0 | sed -e 's/ /:/g')
tmp2=$(sed -e 's/:/\n ..\//g' <<< $libs)
tmp2=../$tmp2
libs=$libs:src
mkdir tmp
#Compile
javac -d tmp -classpath "$libs" src/main/PublishData.java
#Create manifest
cd tmp
echo "Main-Class: main.PublishData" >> m.mf
echo "Class-Path: $tmp2" >> m.mf
#Build jar
jar cvfm thejar.jar m.mf *
m.mf示例文件如下所示:
Main-Class: MyMain
Class-Path: ../libs/1.jar
../libs/2.jar
文件结构如下所示:
├── src
├── tmp (created by the script, jar cvfm thejar.jar m.mf * is run here)
├── libs
│ ├── jar1
│ ├── jar2
创建jar文件并执行,但找不到引用的jar文件。
(例如:Exception in thread "main" java.lang.NoClassDefFoundError: com/mongodb/MongoClient
)
它跟我联系就像jar程序找不到罐子一样。
我怎样才能成功&#34;包括&#34;来自libs dir的罐子吗?
更新:
&#34; Class-Path中的每一行:&#34;清单文件的一部分需要以空格开头和结尾,这导致类路径中断。
答案 0 :(得分:0)
您可以在运行时指定您希望JAR包含哪些JAR。
在您的情况下,以下情况应该有效。
java -cp ../libs/1.jar;../libs/1.jar MyMain
答案 1 :(得分:0)
一般来说,你的方法看起来不错。
相对路径在清单中工作,但您需要确保路径在运行时可用。因此,如果您说“加载../libs/foo.jar
”,那么要使类加载生效,您需要在启动应用程序时加入src/
,tmp/
或libs/
。< / p>
主要问题是Java默默地忽略了无法找到的JAR。我不愿意称这是一个功能,特别是因为很多人在启动Java应用程序时遇到了问题。因此,您必须煞费苦心地找出哪些有效,哪些无效。
为了使事情更简单,我建议你JAR项目的所有类,然后创建一个纯粹的“classpath”JAR(即没有类,只有一个带有类路径+主类的清单文件)。这样,所有依赖项的工作方式都相同。
你应该尝试的另一件事是编写一个小项目(只有hello world类),你可以测试你的“创建清单JAR”脚本。
那就是说,我的方法是创建一个主类,它接受一个路径作为参数(libs文件夹的绝对路径)。然后它会列出文件夹中的所有JAR文件(加上一些调试输出,以便我可以看到它找到的内容),并使用这些URL创建一个新的URLClassLoader
。这样,我可以轻松地调试类路径问题,加上我的“开始”脚本工作如下:
BASE=$(cd $( dirname "$0" ) > /dev/null ; pwd )
java -jar $BASE/starter.jar $BASE/libs