JavaFX可执行JAR跨设备运行报NoSuchMethodError问题求助
Problem Statement
I built a JavaFX-based spellchecker client that runs perfectly in my local Eclipse environment and as an executable JAR on my development laptop. However, when I try to run the same JAR on another machine (which has the same JDK/JRE version installed), I get a cascade of NoSuchMethodError and NullPointerException errors related to JavaFX's native graphics components.
Client Main Code
package SpellcheckerClient; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.layout.BorderPane; public class Main extends Application { @Override public void start(Stage primaryStage) { try { BorderPane root = FXMLLoader.load(getClass().getResource("/controller/gui.fxml")); Scene scene = new Scene(root); scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); primaryStage.setScene(scene); primaryStage.setTitle("Spellchecker Client"); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } }
Controller Code
package controller; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import spellchecker.remote.SpellcheckerRemoteAdapter; public class Controller { @FXML TextField input; @FXML Button send; @FXML TextArea area; @FXML Button connect; private SpellcheckerRemoteAdapter adapter; @FXML private void send() throws RemoteException{ String toCheck = input.getText(); this.area.appendText(toCheck + "\n"); this.area.appendText(checkRoutine(toCheck, this.adapter) + "\n\n"); this.input.clear(); } public void initiateConnection() { try { Registry registry = LocateRegistry.getRegistry(1088); this.adapter = (SpellcheckerRemoteAdapter) registry.lookup(SpellcheckerRemoteAdapter.NAME); this.area.appendText("Verbindung erfolgreich aufgebaut!\n"); connect.setDisable(true); } catch (Exception e) { if(this.adapter == null) { this.area.appendText("Server nicht gefunden!\n"); } } } private static String checkRoutine(String input, SpellcheckerRemoteAdapter adapter) throws RemoteException { if (input == null || input.isEmpty()) { return "Bitte etwas eingeben!"; } String[] words = input.split(" "); boolean control = true; String output = ""; for(String word : words) { if(!adapter.check(word)) { control = false; output += word + ":\t" + adapter.getProposal(word) + "\n"; } } if(control) { return "Alles Okay!\n"; } return output; } }
Error Log
Exception in thread "WindowsNativeRunloopThread" java.lang.NoSuchMethodError: <init> at javafx.graphics/com.sun.glass.ui.win.WinApplication.staticScreen_getScreens(Native Method) at javafx.graphics/com.sun.glass.ui.Screen.initScreens(Unknown Source) at javafx.graphics/com.sun.glass.ui.Application.lambda$run$1(Unknown Source) at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) Exception in thread "WindowsNativeRunloopThread" java.lang.NoSuchMethodError: <init> at javafx.graphics/com.sun.glass.ui.win.WinApplication.staticScreen_getScreens(Native Method) at javafx.graphics/com.sun.glass.ui.Screen.initScreens(Unknown Source) at javafx.graphics/com.sun.glass.ui.Application.lambda$run$1(Unknown Source) at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) Exception in thread "JavaFX Application Thread" java.lang.NullPointerException at javafx.graphics/com.sun.prism.d3d.D3DPipeline.getAdapterOrdinal(Unknown Source) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.assignScreensAdapters(Unknown Source) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runToolkit(Unknown Source) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$startup$10(Unknown Source) at javafx.graphics/com.sun.glass.ui.Application.lambda$run$1(Unknown Source) at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source)
Analysis & Fixes
Let's break down what's happening here: these errors are tied to JavaFX's native graphics layer (the part that interacts directly with Windows' display system) failing to initialize properly. Even if you think both machines have the same JDK/JRE, there are a few common culprits here:
1. Hidden JRE Version Mismatch
It's super common for Windows machines to have multiple JRE/JDK installations (e.g., from old software, system defaults, or other dev tools). Even if you installed the correct version, the system might be picking up a different one when you run the JAR.
Fix:
- On the target machine, open Command Prompt and run:
java -version - Compare the output to your development machine's Java version. If they don't match, update the system's
PATHenvironment variable to put the correct JDK'sbinfolder at the top of the list. Alternatively, run the JAR with an absolute path to the correct Java executable:"C:\Program Files\Java\jdk-17.0.8\bin\java.exe" -jar your-spellchecker-client.jar
2. JavaFX Runtime Not Included (Post-Java 11)
Starting with Java 11, JavaFX is no longer bundled with the JDK. If you just used Eclipse's default JAR export without including JavaFX modules, the target machine won't have the necessary JavaFX libraries to run the app.
Fix:
- Use
jlinkto create a custom runtime image that includes your app and all required JavaFX modules (javafx.controls,javafx.fxml,javafx.graphics). This way, the target machine doesn't need any pre-installed JavaFX. - Alternatively, use
jpackageto build a native Windows installer (EXE/MSI) that packages the runtime and app together—this is the most user-friendly approach for distributing JavaFX apps.
3. Graphics Driver Incompatibility
The D3DPipeline error points to a problem with Direct3D (Windows' hardware acceleration layer). The target machine's graphics driver might be outdated or incompatible with JavaFX's default rendering backend.
Fix:
- Update the target machine's graphics card driver to the latest version (check NVIDIA/AMD/Intel's website for updates).
- If updating doesn't work, force JavaFX to use software rendering (bypassing hardware acceleration) by adding a VM argument when running the JAR:
java -Dprism.order=sw -jar your-spellchecker-client.jar
4. 32-bit vs 64-bit Mismatch
If your development machine uses a 64-bit JDK but the target machine has a 32-bit JRE installed, native JavaFX libraries will fail to load (since they're architecture-specific).
Fix:
- Verify that both machines are running the same architecture (32-bit or 64-bit) of Java. You can check this with:
If it returns an error, you're running a 32-bit JVM.java -d64
Start with checking the Java version and architecture first—those are the easiest fixes. If that doesn't work, try the software rendering flag before diving into repackaging the app.
内容的提问来源于stack exchange,提问作者Linsane

