【问题标题】:making a single-jar java application制作单jar Java 应用程序
【发布时间】:2012-01-08 05:08:34
【问题描述】:

如果我有一个包含几种不同类型的文件(图片、声音等)和多个 jar 依赖项的 java 项目,那么将它们全部打包到一个可以双击的单个 jar 中的好方法是什么?

我知道 jars 本身非常愚蠢,因为它们不会在自己内部寻找它们所依赖的文件(这是我在一点点挫折之后才意识到的(轻描淡写))。 -- 如果 jar A 依赖于 jar B 中包含的类,则将 jar B 放入 jar A 将不起作用。 jar A 必须与 jar B 位于同一目录中。

...现在,我知道我可以从所有其他 jar 中提取所有文件并将所有内容放在同一目录中。这有点工作,但我不想这样做,因为:1。它会很乱,2。它仍然不能解决需要将声音文件放在与最终 jar 相同的目录。 (无论出于何种原因,声音文件的行为方式与内部 jar 完全相同)

基本上,我只是想让我的应用程序所依赖的文件不会令人讨厌地可见和炫耀。因此,如果有一些解决方案可以让我将所有内容都放在一个 jar 中,并让它成为运行整个程序的唯一必要文件,那将是最佳选择。但是,我愿意接受创造性/创造性的方法来绕过问题,例如在父目录中使用批处理脚本执行 jar 或其他东西。 (我说“或某事”是因为那个确切的场景只适用于 Windows 操作系统。...你知道我的意思!)

【问题讨论】:

  • 您如何访问您的资源(声音文件等)?作为文件还是作为 getResource()?
  • 我将他们的文件名传递给 File 对象

标签: java jar executable


【解决方案1】:

Apache Maven 加上shade plugin 将完全满足您的需求。

在此处查看“将主类添加到 MANIFEST.MF 的 Shade 插件”部分http://maven.apache.org/plugins/maven-shade-plugin/examples.html

【讨论】:

    【解决方案2】:

    您可以提取所有 JAR 并将它们合并到一个通用 JAR 中。有 ANT 任务和 Maven 插件可用于执行此操作。此外,如果您的应用程序编写正确,则没有什么能阻止您将媒体文件和其他资源也放入 JAR 中。您只需要确保这些资源是“loaded from the classpath”,而不是从当前工作目录加载。

    【讨论】:

    • 我将如何...“从类路径加载”,究竟是什么?我正在使用两种播放声音的方法;一种是 jmf,它接受声音文件作为 URL 对象,一种是 Clip,它接受声音文件作为 File 对象
    • 你能包含一些绝对的包名/类名吗? javax.sound.sampled.Clip 提供了一种 open(AudioInputStream stream) 方法,可以使用常规 InputStream 实例化该方法 - 例如 getResourceAsStream() 提供的方法。
    • 好吧,使用绝对路径名不是很糟糕..?因为那时您所要做的就是将罐子移到其他地方,突然之间它就不再起作用了。 ...当然,Clip 可以做到这一点,所以我想我现在就去尝试一下,但是使用 jmf,javax.media.Manager 只能从 DataSources、MediaLocators 和 URL 创建播放器。那怎么办?
    • 我根本不建议使用绝对路径名,至少不是文件系统路径。您可以将内容嵌套在类路径中的文件夹中(我建议这样做是为了组织,并防止命名冲突)——所有这些都将包含在您的 JAR 中。我没有对 JMF API 做太多的事情,但是 .getResource() 方法将返回一个指向类路径上资源的 URL——即使在 JAR 中,这可能是受支持的。在最坏的情况下,您可以提供自己的从 InputStream 读取的 PullDataSource 实现。
    【解决方案3】:

    如果你使用maven的组装插件,你可以让它下载依赖,构建模块并生成一个可执行的jar。

    【讨论】:

      【解决方案4】:

      如果您使用 Maven,那么我建议您使用 shade 或程序集插件。 如果没有,请阅读:Easiest way to merge a release into one JAR file

      【讨论】:

        【解决方案5】:

        如果您正在构建一个可执行 jar 并且需要在类路径中提供其他 jar,则 jar 的 MANIFEST.MF 文件中有一个 Class-Path: 行,其中列出了要包含的条目(包括 jar 和目录)在主类运行时的类路径中。

        我通常使用我的 IDE 或 ant 来构建这样的可执行 jar 并设置 Class-Path: 标头。

        顺便说一句,要使您的 jar 可执行,请在您的 MANIFEST.MF 文件中设置 Main-Class: 行。

        这是我构建的可执行 jar 的示例:

        Main-Class: com.example.app.MyAppCLI
        Class-Path: log4j.jar driver.jar libraries.jar
        

        这里有一个相应的 ant 目标来构建它:

        <target name="exejar">
          <jar destfile="myapp.jar"
               basedir="bin"
               include="**/app/*.class">
            <manifest>
              <attribute name="Main-Class" value="com.example.app.MyAppCLI"/>
              <attribute name="Class-Path" value="log4j.jar driver.jar libraries.jar"/>
            </manifest>
          </jar>
        </target>
        

        如果您将使用 ant 之类的工具来构建可执行 jar,它将使该过程更容易重复,并且还会为您处理奇怪的边缘情况,例如当 MANIFEST.MF 中的标题行也出现时会发生什么长。

        【讨论】:

          【解决方案6】:

          如果您使用 Maven,您可能会感谢onejar-maven-plugin。一个主要的好处是你所有的依赖 jar 都保存在 jar 中,而你的代码在它自己的 jar 中。所有这些 jar 都放在一个更大的 jar 中,该 jar 可执行,从而避免了一些潜在的类路径问题。阅读usage guideblog post 了解更多信息。

          【讨论】:

            【解决方案7】:

            有一个由几种不同类型的文件(图片、声音等)和多个 jar 依赖项组成的 java 项目,有什么好方法可以将它们全部打包到一个可以双击的单个 jar 中

            部署富客户端应用的更好方法。正在使用Java Web Start。最终用户永远不会看到 Jar,并且可以提供桌面快捷方式或菜单项来启动应用程序。

            【讨论】:

              猜你喜欢
              • 2014-03-14
              • 1970-01-01
              • 2016-01-19
              • 2019-07-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多