简体   繁体   中英

JavaFx Exception in thread "JavaFX Application Thread" Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger

The app runs perfectly fine in Eclipse and IntelliJ, and also in 'ant run'. Only when I run as Windows cmd to get the following errors:

java -jar TheApp.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

This appears to be a -classpath problem, but I have spent more than one day but still getting the same error.

I'm attaching the build.xml, which works perfectly also:

<?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>

This is my first JavaFx project and I'm trying hard to get it done.

Please help and any insight is greatly appreciated.

You are using at least one 3rd party library (log4j), you may also be using others. You need to also have those libraries on the classpath. Currently, you only have the application jar on the classpath and not the dependent libraries.

You could modify the manifest of your jar to provide the reference to the dependent jars.

Add the following line to the manifest of your jar file.

Class-Path: log4j-core.jar log4j-api.jar

This can probably be done using the manifest element in the ant script (though I have not tried that).

<manifest>
    <attribute name="Main-Class" value="${main-class}"/>
    <attribute name="Class-Path" value="log4j-core.jar log4j-api.jar"/>
</manifest>

Then ensure that the libraries are in the same directory as your jar file with the matching names you specified.

Then you can likely run the app as you were trying to do before (again I didn't try it).

java -jar TheApp.jar

Or, you could run using the -cp option and place all jars (including your jar) on the path, and run the app as:

java -cp TheApp.jar:log4j-core.jar:log4j-api.jar com.th.app.ui.Login

If you have other dependent libraries than just log4j, you will need to ensure they are on the classpath similarly.

There is a process called shading which unpacks all of the jar files used by your application and then repacks them into a single jar which you can execute. I do not recommend shading, but that is an alternate option which I won't detail here.

Such execution will likely only be possible on systems running obsolete versions of the JDK such as Oracle JDK 8. Recent versions of JDKs usually do not ship with the JavaFX framework, which is instead provided through a set of separate modules. The packaging and execution of applications built using recent JavaFX versions are quite different than what you are doing for a JDK 8-based JavaFX application.

Advice for future applications

Use up-to-date libraries, frameworks, and development tools. Follow the official documentation for those software versions. For instance, JDK 18+, JavaFX 18+, information at openjfx.io , Maven or Gradle instead of Ant and jlink or jpackage (usually via a Maven or Gradle plugin) for application packaging.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM