Home > Software design >  java.lang.ClassNotFoundException: application.VideoPlayer
java.lang.ClassNotFoundException: application.VideoPlayer

Time:01-08

)

Not a noob, but a noob question, as Java stuff has happened so long ago in my life, I really feel old now...

Error:

Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: application.VideoPlayer
    at javafx.graphics@19/javafx.application.Application.launch(Application.java:314)
    at application.VideoPlayer.main(VideoPlayer.java:8)
Caused by: java.lang.ClassNotFoundException: application.VideoPlayer
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:495)
    at java.base/java.lang.Class.forName(Class.java:474)
    at javafx.graphics@19/javafx.application.Application.launch(Application.java:302)
    at application.VideoPlayer.main(VideoPlayer.java:8)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:434)
    at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:205)
    at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)

Code, VideoPlayer.java (javafx example code by some stackoverflow user)

package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class VideoPlayer extends Application {    
  public static void main(String[] args) { launch(args); }

  @Override public void start(Stage stage) throws Exception {
    WebView webview = new WebView();
    webview.getEngine().load(
      "http://www.youtube.com/embed/utUPth77L_o?autoplay=1"
    );
    webview.setPrefSize(640, 390);

    stage.setScene(new Scene(webview));
    stage.show();
  }    
}

PATHs JAVA_HOME and PATH_TO_FX are set, bytecode generation completes without warning or error any kind: (I just added all modules I found in the fx directories to rule out something's amiss here...

javac --module-path $PATH_TO_FX --add-modules javafx.base,javafx.controls,javafx.fxml,javafx.graphics,javafx.media,javafx.swing,javafx.web VideoPlayer.java

Now when running the bytecode using

java --module-path $PATH_TO_FX --add-modules javafx.base,javafx.controls,javafx.fxml,javafx.graphics,javafx.media,javafx.swing,javafx.web VideoPlayer.java

the error at this whining's beginning occurs.

Please, I beg you, help me out as it's for sure something incredibly stupid and I'm not only feeling old now for the java stuff so many years in my past but also incredibly stupid.

Thank you, DaBird

PS: I tried to find whatever is missing there, regarding "application.VideoPlayer", nothing of value :-(

PPS: Linux Mint, Java SDK 19, OpenJavaFX from the project's download area, version 19

CodePudding user response:

Preface: If you're new to JavaFX development, or need a refresher, then I recommend reading Getting Started with JavaFX 11 .


Building & Running Project

There are a couple things that are "wrong" with your setup.

Your VideoPlayer class is declared to be in the application package. Yet from your javac command, I gather your VideoPlayer.java file is not under a directory named application. In other words, your project structure should look something like the following:

<working-directory>
\---application
        VideoPlayer.java

Then compile the project with:

javac -p <path-to-javafx> --add-modules javafx.web application/VideoPlayer.java

Note: You only need to add javafx.web in your case, as it transitively requires javafx.base, javafx.graphics, and javafx.controls. Your code isn't using any of the other JavaFX modules.

And then run it with:

java -p <path-to-javafx> --add-modules javafx.web application.VideoPlayer

Notice I used the fully-qualified name of the main class application.VideoPlayer. This is the name of the class, not the name of the source file. You specified the source file in your question (which is part of where your error comes from).

Also, note that the project structure described above is not strictly necessary when compiling. It does, however, matter at run-time (at least with the default ClassLoader implementations). See this other Q&A for more information. Though this is not where your error comes from, at least not directly.

All that said, I recommend using a build tool and/or an IDE when developing JavaFX applications. How to set these up is described in Getting Started with JavaFX 11 . But if you insist on compiling manually, then I recommend using the -d option to set an output directory, as that will create the correct directory structure for the class files regardless of your source file structure.


Your Error

Note this section of my answer only exists to explain your error. If you follow the suggestions above and from Getting Started with JavaFX 11 then this error will no longer apply to you.

Your command to run your application looks like the following:

java -p <path-to-javafx> --add-modules javafx.web VideoPlayer.java

Here you're specifying the source file (VideoPlayer.java). Prior to Java 11 this would have resulted in an error (there's no class named VideoPlayer.java on the class-path). But you're using Java 11 , which means JEP 330: Launch Single-File Source-Code Programs comes into play. This lets you launch a single source file without having to compile it first. It does this internally by compiling the source file into memory. This involves using a separate class loader implementation than "normal", and this is where the error comes from.

You're calling launch(args). That is the Application#launch(String...) method, which is essentially a convenience method for Application#launch(Class,String...) for when the calling class is the application class you want to launch. In your case, the calling class is application.VideoPlayer.

The problem is that Application#launch(String...) uses the calling thread's context class loader to try and get a reference to the calling class's Class. By default, that seems to be the system/application class loader (see documentation of built-in loaders). But that is not the class loader that loaded the application.VideoPlayer class; that class was loaded by an in-memory class loader implementation. Therefore, the class cannot be found when JavaFX attempts to load it. This class loader issue is the reason why your stack trace says application.VideoPlayer could not be found but still show that its main method could be called successfully.

There are two ways to solve this if you're sticking with a single-source file execution.

public static void main(String[] args) {
    // Option 1:
    Thread.currentThread().setContextClassLoader(VideoPlayer.class.getClassLoader());
    launch(args);

    // Option 2:
    launch(VideoPlayer.class, args);
}

Either approach will let the reflection code of JavaFX see your class.

  • Related