该应用程序在Eclipse和IntelliJ中运行良好,在'ant run'中也运行良好。只有当我作为Windows cmd运行时才能得到以下错误:
java -jar
Exception in thread "JavaFX Application Thread" Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
at com.th.app.ui.Login.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplicationWithArgs$2(LauncherImpl.java:352)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:185)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 12 more
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.NullPointerException
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:383)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
... 5 more
这似乎是一个-classpath问题,但我花了一天多的时间,但仍然得到相同的错误。
我正在附加build.xml,它也可以完美地工作:
<?xml version="1.0"?>
<project name="App" default="all" basedir=".">
<property name="src" value="./src"/>
<property name="build" value="./build"/>
<property name="lib" value="./lib"/>
<property name="dest" value="./dest"/>
<property name="main-class" value="com.th.app.ui.Login"/>
<path id="classpath">
<fileset dir="${lib}" includes="**/*.jar"/>
</path>
<target name="all" depends="clean, compile, jar, copy-file" description="Builds the whole project">
<echo>Doing all</echo>
</target>
<target name="clean" description="Removes previous build">
<delete verbose="true">
<fileset dir="${build}"/>
</delete>
</target>
<target name="compile" depends="clean" description="compile whole project">
<echo>compile ${ant.project.name} </echo>
<mkdir dir="${build}/classes"/>
<copy file="./config.properties" tofile="${build}/classes/config.properties"/>
<copy file="./src/log4j.properties" tofile="${build}/classes/log4j.properties"/>
<copy todir="${build}/classes/com/th/app/ui">
<fileset dir="${src}/com/th/app/ui">
<include name="**/*.fxml"/>
<include name="**/*.css"/>
</fileset>
</copy>
<javac srcdir="${src}" destdir="${build}/classes" classpathref="classpath" includeantruntime="false" />
</target>
<target name="jar" depends="compile">
<mkdir dir="${build}/jar"/>
<jar destfile="${build}/jar/${ant.project.name}.jar" basedir="${build}/classes">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
</manifest>
</jar>
</target>
<property name="args" value="READWRITE"/>
<target name="run" depends="copy-file, input-runargs">
<java fork="true" classname="${main-class}">
<classpath>
<path refid="classpath"/>
<path location="${dest}/jar/${ant.project.name}.jar"/>
</classpath>
<arg line="${args}"/>
</java>
</target>
<target name="input-runargs" unless="args" description="prompts for command line arguments if necessary">
<input addProperty="args" message="Type the desired command line arguments:"/>
</target>
<target name="copy-file">
<copy todir="${dest}"><fileset dir="${build}"/></copy>
</target>
</project>
这是我的第一个JavaFx项目,我正在努力把它完成。
请帮忙,任何意见都是非常感谢的。
您正在使用至少一个第三方库(log4j),您也可能正在使用其他库。您还需要在类路径中包含这些库。目前,在类路径上只有应用程序jar,而没有依赖库。
你可以修改你的jar的清单,以提供对依赖jar的引用。
将以下行添加到jar文件的清单中。
Class-Path: log4j-core.jar log4j-api.jar
这可能可以使用ant脚本中的manifest
元素来完成(尽管我没有尝试过)。
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
<attribute name="Class-Path" value="log4j-core.jar log4j-api.jar"/>
</manifest>
然后确保这些库与您指定的jar文件位于相同的目录下,并具有匹配的名称。
然后你可以像之前那样运行应用程序(我也没有尝试过)。
java -jar TheApp.jar
或者,您可以使用-cp选项运行并将所有jar(包括您的jar)放在路径中,并以以下方式运行应用程序:
java -cp TheApp.jar:log4j-core.jar:log4j-api.jar com.th.app.ui.Login
如果您有其他依赖库,而不仅仅是log4j,您将需要确保它们类似地位于类路径上。
有一个叫做shading的过程,它可以解包应用程序使用的所有jar文件,然后将它们重新打包成一个可以执行的jar文件。我不推荐阴影,但这是一个替代选项,我不会在这里详细说明。
这样的执行可能只在运行过时的JDK版本(如Oracle JDK 8)的系统上才有可能。最新版本的jdk通常不随JavaFX框架一起发布,而是通过一组单独的模块提供。使用最新JavaFX版本构建的应用程序的打包和执行与基于JDK 8的JavaFX应用程序的打包和执行是完全不同的。
对未来应用的建议
使用最新的库、框架和开发工具。请参考这些软件版本的官方文档。例如,JDK 18+, JavaFX 18+,信息在openjfx。. io, Maven或Gradle,而不是Ant和jlink
或jpackage
(通常通过Maven或Gradle插件)用于应用程序打包。