요약, 다음 중 하나를 수행 할 수 있습니다.
José의 답변에 --module-path
and --add-modules
like를 통해 JavaFX 모듈을 포함하십시오 .
또는
프로젝트에 JavaFX 라이브러리를 추가했으면 (수동으로 또는 maven / gradle 가져 오기를 통해) module-info.java
이 답변에 지정된 것과 유사한 파일을 추가하십시오 . (이 솔루션은 앱을 모듈화하므로 다른 라이브러리를 사용하는 경우 module-info.java
파일 내에 모듈을 요구하는 명령문도 추가해야 합니다).
이 답변은 Jose의 답변에 대한 보충 자료입니다.
상황은 다음과 같습니다.
- 최신 Java 버전 (예 : 13)을 사용하고 있습니다.
- Maven 프로젝트로 JavaFX 애플리케이션이 있습니다.
- Maven 프로젝트에는 Jose의 답변에 따라 JavaFX 플러그인이 구성되고 JavaFX 종속성이 설정되어 있습니다.
- Application을 확장하는 메인 클래스의 소스 코드로 이동하여 마우스 오른쪽 버튼을 클릭하고 실행 해보십시오.
- 당신은 내려면
IllegalAccessError
응용 프로그램을 실행하려고하면 "이름이 모듈을"포함.
IllegalAccessError
Intellij Idea에서 JavaFX 앱을 실행하려고 할 때 생성되는 스택 추적에 대한 발췌 :
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:567)
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:567)
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:830)
Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x45069d0e) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x45069d0e
at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2056)
at org.jewelsea.demo.javafx.springboot.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(AccessController.java:391)
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)
Exception running application org.jewelsea.demo.javafx.springboot.Main
좋아, 이제 당신은 약간 갇혀 있고 무슨 일이 일어나고 있는지 전혀 모릅니다.
실제로 일어난 일은 다음과 같습니다.
- Maven은 애플리케이션에 대한 JavaFX 종속성을 성공적으로 다운로드 했으므로 종속성을 별도로 다운로드하거나 JavaFX SDK 또는 모듈 배포 등을 설치할 필요가 없습니다.
- Idea는 모듈을 프로젝트에 대한 종속성으로 성공적으로 가져 왔으므로 모든 것이 정상적으로 컴파일되고 모든 코드 완성 및 모든 것이 잘 작동합니다.
그래서 모든 것이 괜찮을 것 같습니다. 그러나 애플리케이션을 실행할 때 리플렉션을 사용하여 애플리케이션 클래스 (시작을 호출 할 때) 및 FXML 컨트롤러 클래스 (FXML을로드 할 때)의 인스턴스를 인스턴스화하려고 할 때 JavaFX 모듈의 코드가 실패합니다. 도움이 없으면 이러한 리플렉션 사용이 실패하여 모호한 IllegalAccessError
. 이는 명시 적으로 허용하지 않는 한 다른 모듈의 코드가 클래스에서 리플렉션을 사용하는 것을 허용하지 않는 Java 모듈 시스템 보안 기능 때문입니다 (그리고 JavaFX 응용 프로그램 시작 관리자 및 FXMLLoader는 모두 기능을 수행하기 위해 현재 구현에서 리플렉션을 필요로합니다. 바르게).
이 질문에 대한 다른 답변 중 일부가 module-info.java
그림에 나오는 곳입니다.
이제 Java 모듈에서 집중 과정을 살펴 보겠습니다.
핵심 부분은 다음과 같습니다.
4.9. 오픈
개인 유형의 반영을 허용해야하지만 모든 코드가 노출되는 것을 원하지 않는 경우 opens 지시문을 사용하여 특정 패키지를 노출 할 수 있습니다.
그러나 이렇게하면 전 세계에 패키지가 열리므로 원하는 것이 있는지 확인하십시오.
module my.module { opens com.my.package; }
따라서 패키지를 전 세계에 공개하고 싶지 않은 경우 다음을 수행 할 수 있습니다.
4.10. 열기…
좋아요, 그래서 반사는 때때로 훌륭하지만 캡슐화에서 얻을 수있는만큼의 보안을 여전히 원합니다. 이 경우 opens… to 지시문을 사용하여 사전 승인 된 모듈 목록에 패키지를 선택적으로 열 수 있습니다.
module my.module {com.my.package를 moduleOne, moduleTwo 등으로 엽니 다. }
따라서 다음과 같은 src / main / java / module-info.java 클래스를 생성하게됩니다.
module org.jewelsea.demo.javafx.springboot {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
opens org.jewelsea.demo.javafx.springboot to javafx.graphics,javafx.fxml;
}
여기서는 org.jewelsea.demo.javafx.springboot
JavaFX 응용 프로그램 클래스 및 JavaFX 컨트롤러 클래스를 포함하는 패키지의 이름입니다 (이를 응용 프로그램에 적합한 패키지 이름으로 대체). 이것은 클래스에 대한 확인이에 있는지 자바 런타임 이야기 javafx.graphics
와 javafx.fxml
당신의 클래스에 호출 반사에 org.jewelsea.demo.javafx.springboot
패키지를. 이 작업이 완료되고 응용 프로그램이 컴파일되고 다시 실행되면 제대로 작동 IllegalAccessError
하고 JavaFX의 리플렉션 사용에 의해 생성 된 작업 이 더 이상 발생하지 않습니다.
하지만 module-info.java 파일을 만들고 싶지 않다면
IDE의 상단 도구 모음에있는 실행 버튼을 사용하여 애플리케이션 클래스를 직접 실행하는 대신 다음을 수행합니다.
- IDE 측면의 Maven 창으로 이동했습니다.
- javafx maven 플러그인 대상을 선택했습니다
javafx.run
.
- 그것을 마우스 오른쪽 버튼으로 클릭하고
Run Maven Build
또는을 선택하십시오 Debug...
.
그러면 앱이 module-info.java
파일 없이 실행 됩니다. 나는 이것이 module-info.java
어떻게 수행되는지 모르겠지만 maven 플러그인이 파일 없이도 JavaFX 클래스에 의해 앱이 반영되도록하는 일종의 설정을 동적으로 포함 할 수있을만큼 똑똑하기 때문이라고 생각합니다 .
해당 설정을 상단 도구 모음의 실행 버튼으로 전송하려면 javafx.run
Maven 대상을 마우스 오른쪽 버튼으로 클릭 Create Run/Debug Configuration
하고 대상 에 대한 옵션을 선택합니다 . 그런 다음 상단 툴바에서 Run을 선택하여 Maven 타겟을 실행할 수 있습니다.