不用直接调用“java”,运行JAR文件的方法

23
我正在部署一个用Java编写的命令行工具,它接受命令行参数。我将其打包成了一个JAR文件,因为这样只需要一个文件非常方便。
问题在于要运行它,你必须首先调用java -jar (filename) (args),这很麻烦。
我目前的做法是使用一个简单的bash脚本来启动它,但这不是最理想的方法。
在Linux、Ubuntu Server上,有没有办法制作一个可以自己调用Java虚拟机的JAR文件?我找过shebang,但没有找到(当然,这是因为它是编译代码)。
我想做的是:myprogram.jar arg1 -arg2 而不是这样的:java -jar myprogram.jar arg1 -arg2 谢谢, Brian

没有一个答案提出更好的解决方案。我在某个地方读到过,你可以在jar文件顶部基本上连接一个shell命令。不太优雅,但非常方便。https://mesosphere.com/blog/executable-jars/ - Sridhar Sarnobat
3个回答

44

基于压缩文件格式的 .zip 文件似乎可以在文件前添加额外数据的情况下保持稳健。因此,如果使用 cat 命令将 shebang 添加到 jar 文件中 zip 数据之前,并使文件可执行,则可以像调用任何普通 shell 脚本一样调用 jar 文件。

例如: (请注意,unzip -l 命令只是为了说明这一点。它不会改变 .jar 文件的任何内容,在实际执行此过程时可以省略该命令。)

[bloom@cat-in-the-hat ~]$ java -jar tex4ht.jar 
   xtpipes (2009-01-27-22:19)
   Command line options: 
     java xtpipes [-trace] [-help] [-m] [-E] [-s script_file] [-S script_map]
                  [-i script_dir] [-o out_file] 
                  [-x...ml2xml_arg...]  (-d in_data | in_file)
     -m        messages printing mode
     -E        error messages into exception calls
     in_data   XML data directly into the command line

[bloom@cat-in-the-hat ~]$ cat header.txt 
#!/usr/bin/java -jar
[bloom@cat-in-the-hat ~]$ cat header.txt tex4ht.jar > tex4ht_exe.jar 
[bloom@cat-in-the-hat ~]$ unzip -l tex4ht_exe.jar
Archive:  tex4ht_exe.jar
warning [tex4ht_exe.jar]:  21 extra bytes at beginning or within zipfile
  (attempting to process anyway)
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2009-07-09 15:48   META-INF/
       42  2009-07-09 15:47   META-INF/MANIFEST.MF
        0  2009-07-09 15:48   ./
        0  2009-07-09 15:48   tex4ht/
     2217  2009-07-09 15:48   tex4ht/DbUtilities.class
     2086  2009-07-09 15:48   tex4ht/GroupMn.class
     6064  2009-07-09 15:48   tex4ht/HtJsml.class
     4176  2009-07-09 15:48   tex4ht/HtSpk.class
     1551  2009-07-09 15:48   tex4ht/JsmlFilter.class
     2001  2009-07-09 15:48   tex4ht/JsmlMathBreak.class
     6172  2009-07-09 15:48   tex4ht/OoFilter.class
     3449  2009-07-09 15:48   tex4ht/OoUtilities.class
     1468  2009-07-09 15:48   tex4ht/OomFilter.class
      346  2009-07-09 15:48   xtpipes.class
        0  2009-07-09 15:48   xtpipes/
     4071  2009-07-09 15:48   xtpipes/FileInfo.class
     6904  2009-07-09 15:48   xtpipes/InputObject.class
    25906  2009-07-09 15:48   xtpipes/Xtpipes.class
     1238  2009-07-09 15:48   xtpipes/Xtpipes$5.class
      713  2009-07-09 15:48   xtpipes/Xtpipes$3.class
     1533  2009-07-09 15:48   xtpipes/Xtpipes$1.class
      709  2009-07-09 15:48   xtpipes/Xtpipes$7.class
     1294  2009-07-09 15:48   xtpipes/XtpipesEntityResolver.class
     1235  2009-07-09 15:48   xtpipes/Xtpipes$6.class
     3367  2009-07-09 15:48   xtpipes/Xtpipes$4.class
      709  2009-07-09 15:48   xtpipes/Xtpipes$8.class
     1136  2009-07-09 15:48   xtpipes/Xtpipes$2.class
      875  2009-07-09 15:48   xtpipes/XtpipesPrintWriter.class
     1562  2009-07-09 15:48   xtpipes/XtpipesUni.class
        0  2009-07-09 15:48   xtpipes/util/
     5720  2009-07-09 15:48   xtpipes/util/ScriptsManager.class
     1377  2009-07-09 15:48   xtpipes/util/ScriptsManagerLH.class
---------                     -------
    87921                     32 files
[bloom@cat-in-the-hat ~]$ chmod +x tex4ht_exe.jar
[bloom@cat-in-the-hat ~]$ ./tex4ht_exe.jar 
   xtpipes (2009-01-27-22:19)
   Command line options: 
     java xtpipes [-trace] [-help] [-m] [-E] [-s script_file] [-S script_map]
                  [-i script_dir] [-o out_file] 
                  [-x...ml2xml_arg...]  (-d in_data | in_file)
     -m        messages printing mode
     -E        error messages into exception calls
     in_data   XML data directly into the command line

3
这是一个非常有趣的解决方案,虽然相当不传统。 - Daniel Pryden
1
@Daniel:同意。binfmt_misc解决方案肯定更加干净,但这是一个非常酷的技巧;-) - Joachim Sauer
我不知道ZIP格式的设计者的想法,但我认为这实际上是一个经过设计的特性。JAR格式只是一个围绕着预定目录结构和一些元数据文件的ZIP容器,而ZIP格式有意将其“标头”信息实际上放在页脚中,其中一部分特别是“数据开始”地址。在我看来,这很可能是为了允许文件开头的可执行数据,从而实现自解压缩存档。 - tophyr
@tophyr:你说得对!这确实在维基百科上。感谢你指出来。 - Ken Bloom
3
不要这样做。这样修改过的JAR会破坏我的SBT构建,因为尽管JAR文件在类路径上,但其中的类仍然无法被找到。删除shebang指令可以解决这个问题。 - ComFreek
显示剩余7条评论

18

请查看Linux内核文档中的Documentation/java.txt,这将告诉您如何使用binfmt_misc内核模块配置系统以自动运行Jar文件。但是,这是一项在计算机上更改的配置选项,而不是您更改的有关Jar文件的内容,因此它不会随着Jar文件从一个系统迁移到另一个系统。


这似乎是个好主意,但我无法负担在所有生产机器上安装SDK的费用。不过对目标盒子进行小改动我倒是没有问题。我非常惊喜Linux实现了这一点,非常令人印象深刻。 - HalfBrian
1
你不需要完整的JDK(带有编译器)来使其工作。JRE(无论如何,你在生产机器上都需要)应该就可以了。 - Ken Bloom
哇!这是一个很棒的工具。即使没有SDK,也运行得非常好。非常感谢。 - HalfBrian

4
在基于Debian的发行版上,可以安装jarwrapper。
sudo apt-get install jarwrapper

我认为只要安装相同的软件包名称,就可以在其他发行版上完成相同的操作。

运行得很好。谢谢。 - Fiddy Bux

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