如何运行使用'lein jar'命令生成的jar文件?

15

这是这个问题的后续。

运行 "lein jar" 后,我得到了 "myproject-1.0.0-SNAPSHOT.jar",但它不包含 "clojure-1.2.0-beta1.jar" 和 "clojure-contrib-1.2.0-beta1.jar"。

而运行 "lein uberjar" 则会给我两个 jar 文件。第一个文件(以 "-standalone.jar" 结尾)包含了所有内容,而第二个文件与用 "lein jar" 生成的文件相同。

这就是第二个 jar 文件的问题所在。如我在前面的帖子中所解释的那样,使用第一个 jar 文件没有问题。

当我运行

java -cp PATH_TO_THE_CLOJURE_AND_CONTRIB.jar:$CLASSPATH -jar myproject-1.0.0-SNAPSHOT.jar'

时,我遇到了以下错误。

Caused by: java.lang.ClassNotFoundException: clojure.lang.IFn
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
如果我使用-cp选项指向jar文件,我是否可以像使用'myproject-1.0.0-SNAPSHOT-standalone.jar'一样使用'myproject-1.0.0-SNAPSHOT.jar'?有没有其他需要做的事情?

已添加

java -cp ALLTHE_JAR_PATH myproject.core
解决了这个问题。
1个回答

13
如果您正在使用Leiningen 1.2,那么您可能会遇到一个bug,即依赖关系会在创建uberjar之前被删除(显然违背了uberjar的目的)。请降级到1.1并等待新版本发布(很快就会到来),或者使用lein的HEAD的检查(如在lein的README中关于hack Leiningen的部分所述)。
一旦您这样做了,您应该能够用 lein uberjar 生成一个独立的jar包,并使用 java -jar name-of-your-standalone.jar 来启动您的应用程序。
作为替代方案,您可以用 lein jar 创建一个常规的jar包,然后使用类似于 java -cp '$PROJECT_ROOT/lib/*:your-app.jar' your-app.main 的方式运行它(其中your-app.main是您的应用程序的主类;同时,请将$PROJECT_ROOT 替换为适当的路径,并当然要提供一个路径来指定 your-app.jar)。请注意,在使用-jar时,-cp$CLASSPATH会被忽略;只有在jar的清单中指定的类路径(如果有)才会被考虑。

我的uberjar没有任何问题,我想知道为什么从'lein jar'获取的jar文件不能用'java -cp $PROJECT_ROOT/lib*' -jar your-app.jar运行。我是否需要将your-app.jar放入-cp中?那么,我还需要调用哪个命令? - prosseek
如果您指定了 -jar,则会忽略 -cp(以及 $CLASSPATH)。 您必须使用 -cp 并手动指定主类(如果它被称为 your-app.main,请说 java -cp ... your-app.main,并在末尾添加任何传递给您的 main 方法(= Clojure 函数 -main)的参数)。我应该在阅读问题时注意到这一点...将其编辑到答案中。 - Michał Marczyk
顺便提一句,如果uberjar为您创建的JAR文件不包括clojure.jarclojure-contrib.jar的内容,则它可能存在问题。包含依赖项是使用uberjar的全部意义所在!(这使得使用java -jar命令成为可能。) - Michał Marczyk
2
1.2版本的另一个解决方法是在project.clj中包含一个:main命名空间;如果您正在构建用于分发的uberjar,则可能需要一个-main函数。在过程中包括AOT可以避免清除jar文件的错误。 - user61051
啊,对了。我猜 -jar 模式下肯定是需要的。感谢你指出来! - Michał Marczyk
uberjar 只是为我运行了 repl。我发誓这以前可行过。 - Justin Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接