JavaFX 11: IllegalAccessError saat membuat Label

Pertanyaan ini kemungkinan besar mengenai masalah yang sama dengan yang ini, namun tampaknya penanya belum menambahkan informasi yang cukup untuk menerima tanggapan yang membantu.

Saya mencoba menjalankan aplikasi JavaFx dengan JDK dan JavaFx SDK versi 11.0.2.

Kode ini berfungsi persis seperti yang diharapkan, menghasilkan jendela kosong:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    public void start(Stage primaryStage) throws Exception {
        StackPane root = new StackPane();
        primaryStage.setScene(new Scene(root, 420, 420));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

Namun, jika saya mencoba menambahkan label ke StackPane, pengecualian akan muncul.

import ...
import javafx.scene.control.Label;

public class Main extends Application {

    public void start(Stage primaryStage) throws Exception {
        StackPane root = new StackPane();
        root.getChildren().add(new Label("42"));
        primaryStage.setScene(new Scene(root, 420, 420));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

Jejak tumpukan yang dihasilkannya terlihat seperti ini (baris 13 di Utama adalah tempat Label dibuat):

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalAccessError: superclass access check failed: class com.sun.javafx.scene.control.ControlHelper (in unnamed module @0xbbd2743) cannot access class com.sun.javafx.scene.layout.RegionHelper (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.scene.layout to unnamed module @0xbbd2743
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at javafx.scene.control.Control.<clinit>(Control.java:86)
    at sample.Main.start(Main.java:13)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
    ... 1 more
Exception running application sample.Main

Saya menjalankan IntelliJ Idea versi terbaru di Kubuntu. Saya mengunduh Oracle JDK dan juga JavaFX, dari situs resminya

Saya meletakkan javafx-sdk-11.0.2 di direktori /usr/lib/jvm/ dan jdk-11.0.2 di direktori yang sama.

Di IntelliJ Idea, saya yakin saya telah memilih JDK dengan benar, dan saya telah menambahkan /usr/lib/jvm/javafx-sdk-11.0.2/lib sebagai perpustakaan.

IntelliJ Idea menggunakan perintah ini untuk meluncurkan Aplikasi (dipisahkan agar mudah dibaca):

/usr/lib/jvm/jdk-11.0.2/bin/java
  -Djava.library.path=/usr/lib/jvm/javafx-sdk-11.0.2/lib
  --add-modules javafx.base,javafx.graphics
  --add-reads javafx.base=ALL-UNNAMED
  --add-reads javafx.graphics=ALL-UNNAMED
  -javaagent:/opt/jetbrains/idea-IU-183.4886.37/lib/idea_rt.jar=36031:/opt/jetbrains/idea-IU-183.4886.37/bin
  -Dfile.encoding=UTF-8
  -classpath
    /home/rm/IdeaProjects/JfxPlayground/out/production/JfxPlayground
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/src.zip
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx-swt.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.web.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.base.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.fxml.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.media.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.swing.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.controls.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.graphics.jar
  -p
    /usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.base.jar
    :/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.graphics.jar
  sample.Main

Saya belum mengubah opsi VM apa pun.

Bagaimana cara memperbaiki kesalahan ini? Apakah ini bug di JavaFx?


person Reinis Mazeiks    schedule 21.01.2019    source sumber
comment
Saat menjalankan modul, Anda tidak boleh menggunakan deklarasi classpath, dan sebaliknya.   -  person Dragas    schedule 13.12.2020


Jawaban (4)


Anda sudah memberikan penjelasan tentang masalah Anda:

Saya belum mengubah opsi VM apa pun.

Karena JavaFX 11 bukan lagi bagian dari JDK, Anda harus menggunakan JavaFX SDK (seperti yang Anda lakukan) dari di sini, atau alternatifnya gunakan Maven/Gradle untuk mengambil modul JavaFX dari Maven Central.

Kemudian Anda perlu menambahkan SDK sebagai perpustakaan, sehingga IntelliJ dapat menemukan kelas JavaFX.

Namun setelah Anda selesai melakukannya, dan mengingat toples JavaFX adalah modul, Anda masih perlu melakukan dua hal:

  • Jadikan modul JavaFX tersedia untuk jalur modul Anda
  • Tentukan modul mana yang Anda tambahkan ke proyek

Berdasarkan keluaran IntelliJ Anda, secara default ditambahkan javafx.graphics dan javafx.base:

--add-modules javafx.base,javafx.graphics

-p /usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.base.jar
:/usr/lib/jvm/javafx-sdk-11.0.2/lib/javafx.graphics.jar

(perhatikan bahwa -p sama dengan --module-path)

Ini menjelaskan mengapa proyek Anda berjalan dalam kasus pertama, ketika Anda tidak memiliki kontrol yang ditambahkan ke adegan, hanya StackPane, yang merupakan milik javafx.graphics modul, tetapi gagal dengan pengecualian yang diposting saat Anda menambahkan Label, yang termasuk dalam javafx.controls modul.

Hal ini telah dikatakan beberapa kali: Anda perlu menyetel opsi VM yang diperlukan untuk proyek Anda.

Mulailah dengan membaca dokumentasi di https://openjfx.io/openjfx-docs/, termasuk < dokumen href="https://openjfx.io/openjfx-docs/#IDE-Intellij" rel="noreferrer">IntelliJ, bagian Proyek non-modular untuk IDE Anda. Dan baca bagian 4. Tambahkan opsi VM.

Opsi VM

Jadi klik Jalankan -> Edit Konfigurasi, dan tambahkan:

-p /usr/lib/jvm/javafx-sdk-11.0.2/lib --add-modules javafx.controls

Terapkan, dan jalankan, masalah akan terpecahkan.

person José Pereda    schedule 21.01.2019
comment
apakah ada cara untuk melakukan hal yang sama tanpa menentukan opsi VM? - person user2914191; 15.02.2019
comment
@ user2914191Jalankan javafx:run dari jendela Maven. - person ItachiUchiha; 02.08.2019
comment
Daripada mengunduh SDK atau pustaka JavaFX, opsi lainnya adalah menggunakan JDK yang menyertakan pustaka JavaFX/OpenJFX. Setidaknya ada dua produk tersebut: LibericaFX dari BellSoft, dan JDK FX yang dibuat dari Azul Platform Core dari Azul Systems. - person Basil Bourque; 05.06.2021

Saya akan menggunakan gradle dan plugin javafx untuk itu.

apply plugin: "org.openjfx.javafxplugin"

javafx {
    version = "11"
    modules = ["javafx.base", "javafx.controls", "javafx.graphics"
}
person Beowolve    schedule 13.10.2020

Pilihan lain mungkin berguna, terutama jika Anda berencana mengemas aplikasi Anda sebagai fat-jar.

Terima kasih kepada jawaban ini.

Daripada memodifikasi opsi vm, Anda dapat membuat kelas Main lain yang tidak memperluas javafx.application.Application dan memanggil metode awal aplikasi Anda dari sana. Coba yang berikut ini:

public class App extends Application
{

    @Override public void start(Stage stage)
    {
        // all the stuff necessary
    }

    // Method called "main" here for experimental purposes.
    // But for production use you may decide to call it, "run" for example.
    // Exact name does not matter.
    public static void main(String[] args)
    {
        App.launch();
    }

}

// This class must NOT extend Application. It is a wrapper only.
public class Runner
{
    public static void main(String[] args)
    {
        // Starter method from previous class
        App.main(args);
    }
}

Mencoba menjalankan App.main() dengan konfigurasi default (VM options adalah kolom kosong) akan menyebabkan kesalahan, sementara Runner.main() berhasil dijalankan.

Untuk pemahaman lebih dalam, Anda dapat membandingkan perintah java run (ide melipatnya secara default) yang ditemukan di jendela Run atau Debug.

person Boris    schedule 30.03.2021

periksa JAVA_HOME Anda, versi JAVA_HOME harus jdk9+ atau jdk11+

person 远星河    schedule 25.05.2020