6

我一直在研究一个命令行可执行的 Java 程序。它处于测试阶段,并且将其打包已被证明是一个问题。这个问题的症结在于我的应用程序有许多依赖项。我的 lib 文件夹(包含 jars)接近 500mb。

目前我一直在使用 Eclipse Runnable Jar Export 向导。工作完美,除了它必须从 Eclipse 完成。它会生成一个大小约为 500mb 的 Jar(不要问......我只想说需要在这个程序中打包很多 COBOL 程序)。这个过程需要<30s。

理想情况下,我希望这是某种 Ant 任务,可通过 Jenkins 运行并发布到存储库。这样用户就可以抓住一个 Jar 并运行它。

我调查过的选项:

自定义类加载器(FatJar、OneJar 等)。

  • 作品
  • 运行时执行缓慢,因为需要解压 jar。
  • 文件结构基本上是一个装满 jar 的 Jar,主类通过自定义类加载器委托。
  • 快速构建时间(5 分钟)

    <target name="hello" depends="compile">
        <property name="classes.dir" value="onejar" />
        <property name="build.dir" value="bin" />
    
        <one-jar destfile="hello.jar">
            <manifest>
                <attribute name="One-Jar-Main-Class" value="mainclass" />
                <attribute name="Class-Path" value="." />
                <attribute name="One-Jar-Show-Expand" value="true" />
            </manifest>
            <main>
                <fileset dir="${build.dir}"/>
            </main>
            <lib>
                <fileset dir="lib">
                    <include name="**/*.jar"/>
                </fileset>
    
            </lib>
    
    
        </one-jar>
    </target>
    

手动收集依赖项,将它们解压缩到一个文件夹中,然后使用自定义 MANIFEST 文件将它们全部组合起来。

  • 无法让它工作
  • 大 (1500mb+)
  • 构建时间慢(20 分钟 +)

    <target name="compile" depends="resolve">
        <javac srcdir="src" destdir="bin" debug="true" deprecation="on">
            <classpath>
                <path refid="ivy.path" />
            </classpath>
        </javac>
    </target>
    
    
    
    <target name="jar" depends="compile" description="Create one big jarfile.">
        <jar jarfile="${dist}/deps.jar">
            <zipgroupfileset dir="lib">
                <include name="**/*.jar" />
            </zipgroupfileset>
        </jar>
        <sleep seconds="1" />
        <jar jarfile="${dist}/myjar.jar" basedir="bin">
            <zipfileset src="${dist}/deps.jar" excludes="META-INF/*.SF" />
            <manifest>
                <attribute name="Main-Class" value="mymainclassishere" />
            </manifest>
        </jar>
    </target>
    

所以,是的,有人有什么建议吗?我很想听听人们的想法。

编辑:特别......为什么Eclipse Runnable Jar Export Wizard可以在不到30秒的时间内导出我的Jar,但我的构建时间> 30分钟。

4

1 回答 1

4

我知道回答你的问题可能会令人不悦,但我昨天确实设法解决了这个问题。在我尝试的所有选项中,我发现最快的解决方案是复制 Eclipse Runnable Jar Export Wizard。它需要jar-in-jar-loader.zip可以使用 Runnable Jar Export Wizard 获取的...或者您可以通过 Google/Eclipse 安装找到它。

我发现这个解决方案构建速度很快(30 秒)并且运行速度更快(5 秒启动成本)。它还使罐子结构非常整洁,没有爆炸的罐子。

<target name="compile" depends="resolve">
    <mkdir dir="bin"/>
    <!-- Copy all non java resources since jar javac will exclude them by default. Needed for xmls, properties etc --->
    <copy todir="bin">
        <fileset dir="src" excludes="**/*.java" />
    </copy>

    <javac srcdir="src" destdir="bin" debug="true" deprecation="on">
        <classpath>
            <path refid="ivy.path" />
        </classpath>
    </javac>
</target>


<!-- Creates the runnable jar. Copies the dependencies as jar files, into the top level of a new jar. 
     This means nothing without a custom classloader and manifest with a jar listing -->
<target name="jar" depends="compile" description="Create one big jarfile.">

    <path id="dependencies.path">
        <fileset dir="lib">
            <include name="**/*.jar" />
        </fileset>
    </path>

    <pathconvert property="manifest.classpath" pathsep=" ">
        <path refid="dependencies.path" />
        <mapper>
            <chainedmapper>
                <flattenmapper />
                <globmapper from="*.jar" to="*.jar" />
            </chainedmapper>
        </mapper>
    </pathconvert>

    <mkdir dir="${dist}"/>
    <jar destfile="${dist}/jar/Runnable.jar" filesetmanifest="mergewithoutmain">
        <manifest>
            <attribute name="Main-Class" value="org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader" />
            <attribute name="Rsrc-Main-Class" value="mymainclass" />
            <attribute name="Class-Path" value="." />
            <attribute name="Rsrc-Class-Path" value="./ ${manifest.classpath}" />
        </manifest>
        <fileset dir="bin" />
        <zipfileset src="jar-in-jar-loader.zip" />
        <zipfileset dir="lib" includes="**/*.jar*" />
    </jar>
</target>
于 2012-04-21T06:58:51.240 回答