从bash创建一个带依赖关系的jar

时间:2014-11-18 13:48:12

标签: java bash jar classpath

首先,我想说我不想使用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;清单文件的一部分需要以空格开头和结尾,这导致类路径中断。

2 个答案:

答案 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