无法将带有外部库的JavaFX应用程序部署到JAR中。

4
我正在Eclipse中开发一个JavaFX应用程序,该应用程序有外部库,如log4j等,并且可以在Eclipse中正常运行。我尝试使用Eclipse内置功能将其部署为可运行的JAR文件,并在某些计算机上成功运行,而在其他计算机上会出现模糊的未定义链接错误。经过调查,似乎需要通过ANT脚本或javafxpackager应用程序特殊打包JavaFX。

但是我试图使用这些方法之一部署可运行的jar文件,都会导致异常。我尝试过的方法有:

  1. Build the JavaFX application through an ANT script, below is a snippet of the relevant parts of the build script

    <path id="classpath">
        <fileset dir="${lib.dir}" includes="**/*.jar"/>
        <fileset dir="${javafx.sdk.path}/jre/lib" includes="jfxrt.jar"/>
    </path>
    
    <target name="compile" depends="clean">
        <echo>Compiling the source</echo>  
        <mkdir dir="${classes.dir}"/>
        <!-- Copy over the misc files into the classes dir -->
        <copy todir="${classes.dir}/bundles">
           <fileset dir="${src.dir}/bundles"/>
        </copy>
        <copy todir="${classes.dir}/css">
            <fileset dir="${src.dir}/css"/>
        </copy>
        <copy todir="${classes.dir}/img">
           <fileset dir="${src.dir}/img"/>
        </copy>
        <copy todir="${classes.dir}/views">
           <fileset dir="${src.dir}/views"/>
        </copy>
    
        <copy todir="${classes.dir}/bundles">
           <fileset dir="${src.dir}/bundles"/>
        </copy>
    
        <copy file="${src.dir}/log4j2.xml" todir="${classes.dir}"/>
    
        <javac target="1.7" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" debug="on">
        </javac>
    </target>
    
    <target name="jar" depends="compile">
        <echo>Creating the main jar file</echo>  
        <mkdir dir="${distro.dir}" />
        <fx:jar destfile="${distro.dir}/main.jar" verbose="true">
            <fx:platform javafx="2.1+" j2se="7.0"/>
            <fx:application mainClass="${main.class}"/>
    
            <!-- What to include into result jar file?
                 Everything in the build tree-->
            <fileset dir="${classes.dir}"/>
    
            <!-- Define what auxilary resources are needed
                  These files will go into the manifest file,
                  where the classpath is defined -->
             <fx:resources>
                <fx:fileset dir="${distro.dir}" includes="main.jar"/>
                <fx:fileset dir="." includes="${lib.dir}/**" type="jar"/>
                <fx:fileset dir="." includes="."/>
            </fx:resources>
    
            <!-- Make some updates to the Manifest file -->
            <manifest>
               <attribute name="Implementation-Vendor" value="${app.vendor}"/>
               <attribute name="Implementation-Title" value="${app.name}"/>
               <attribute name="Class-Path" value="${lib.dir}"/> 
               <attribute name="Implementation-Version" value="1.0"/>
            </manifest>
        </fx:jar>
    </target>
    
通过ant脚本编译/生成jar时,弹出一个半秒钟的窗口,并在控制台中显示“应用程序启动方法中的异常”,但没有堆栈跟踪。我尝试使用-XX:-OmitStackTraceInFastThrow标志运行java,但它仍然不会给我堆栈跟踪。
通过javafxpackager运行时出现以下错误: RenderJob.run: 内部异常 java.lang.UnsatisfiedLinkError: com.sun.prism.d3d.D3DContext.nSetBlendEnabled(JZ Z)I at com.sun.prism.d3d.D3DContext.nSetBlendEnabled(Native Method) at com.sun.prism.d3d.D3DContext.initState(D3DContext.java:84) at com.sun.prism.d3d.D3DResourceFactory.(D3DResourceFactory.java:5 7) at com.sun.prism.d3d.D3DPipeline.createResourceFactory(D3DPipeline.java: 147) at com.sun.prism.d3d.D3DPipeline.getD3DResourceFactory(D3DPipeline.java: 153) at com.sun.prism.d3d.D3DPipeline.findDefaultResourceFactory(D3DPipeline. java:179) at com.sun.prism.d3d.D3DPipeline.getDefaultResourceFactory(D3DPipeline.j ava:201) at com.sun.prism.GraphicsPipeline.getDefaultResourceFactory(GraphicsPipe line.java:97) at com.sun.javafx.tk.quantum.QuantumRenderer$3.run(QuantumRenderer.java: 143) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:47 1) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) at com.sun.prism.render.RenderJob.run(RenderJob.java:37) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor. java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor .java:615) at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(Quantu mRenderer.java:98) at java.lang.Thread.run(Thread.java:724)
3个回答

3
您可以使用 javafxpackager 部署您的应用程序。如果部署一个自包含的应用程序,Java运行时环境将与您的应用程序捆绑在一起,并且它将在任何计算机上运行,无论是否安装了正确版本的Java。 (您应该在bin文件夹下的jdk目录中拥有 javafxpackager
  1. 查找您在eclipse工作区文件夹中编译的文件 (.class)。它们应该在bin目录中。

  2. 创建一个createjar文件夹,在其中创建一个classes和一个out文件夹。将所有 .class 文件复制到classes文件夹中。还包括在classes文件夹中应用程序所需的所有 jar 包。

  3. 现在在命令行中进入createjar目录并运行此命令:

    "C:\path\to\jdk\jdk1.7.0_25\bin\javafxpackager.exe" -createjar -appclass package.MainClass -srcdir classes -outdir out -outfile NameOfYourJar -classpath "" -v

这将在out目录中创建可运行的jar文件。您需要它进行下一步操作。

  1. 现在在createjar文件夹旁边创建一个deploy文件夹。

  2. deploy文件夹中创建两个其他目录distpackages

  3. dist文件夹中复制您上面新创建的jar文件以及所有它需要的依赖关系/资源。

回到命令行(如果您曾离开过),进入deploy目录。从那里运行以下命令:

"C:\path\to\jdk\jdk1.7.0_25\bin\javafxpackager.exe" -deploy -native -outdir packages -outfile NameOfYourApp -srcdir dist -srcfiles NameOfYourJar.jar -appclass package.MainClass -name "Name of You Application" -title "Title of your application"

一旦完成,它应该已经创建了部署您的应用程序所需的所有内容,包括在Windows平台上运行的本地.exe文件。这是一个自包含的应用程序!要运行它,您需要进入bundles\NameOfYourApp\app并在此处粘贴应用程序所需的所有依赖项/资源。

最后,双击YourApp.exe,即可在没有安装Java的计算机上运行。


1
使用ant文件有两个主要选项:<fx:jar><fx:deploy>。前者只生成一个jar文件,如果您的依赖项与jar文件位于同一文件中,则可以引用它们。您可以解压缩jar文件并查看生成的MANIFEST文件,以了解它们如何添加到javafx类路径中。 <fx:deploy>允许您引入依赖项,但需要构建特定于平台的安装程序。它不能使用jar文件完成。显然,NetBeans允许您创建一个独立的jar文件,但我还没有测试过。

0
  1. 你没有将javafxrt.jar与你的应用程序一起打包
  2. 如果你使用e(fx)clipse,它会为你生成ant脚本

  1. 新版JRE中不是已经捆绑了javafxrt吗?
  2. 我尝试使用e(fx)clipse生成的ANT脚本,但没有成功。
- alexb
打包是的确进行了,但它并不在类路径上,因此javafxpackager会向您的MANIFEST.MF添加一个主类来定位它并构建一个专用的类加载器。在Java8中,它在扩展类路径上,因此不再需要这个技巧。 - tomsontom

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