我一直在用Java编写自己的小项目,最近,我编译了它并收到了这个错误:
线程“main”中的异常java.lang.IllegalAccessError:超类访问检查失败:类kröw.zeale.v1.program.core.DataManager$ ConstructList(在未命名模块@ 0x4563e9ab中)无法访问类com.sun.javafx。 collections.ObservableListWrapper(在模块javafx.base中)因为模块javafx.base没有将com.sun.javafx.collections导出到未命名的模块@ 0x4563e9ab
所以,我目前有三个不同的类,都在同一个包中。我的层次结构如下:
• Kröw
• DataManager
♦ ConstructList
在我的程序的早期版本中,我的层次结构是这样的:
• Kröw
♦ DataManager
- ConstructList
在这两种情况下,ConstructList
都延长了com.sun.javafx.collections.ObservableListWrapper<Construct>
。 (我不认为班级Construct
在这里是必要的,我宁愿不展示它,但如果需要,我可以。)
无论如何,现在,我的IDE可以按预期运行应用程序,但是,当我导出它时,会给我上面的异常。
完整堆栈跟踪:
Exception in thread "main" java.lang.IllegalAccessError: superclass access check failed: class kröw.zeale.v1.program.core.DataManager$ConstructList (in unnamed module @0x4563e9ab) cannot access class com.sun.javafx.collections.ObservableListWrapper (in module javafx.base) because module javafx.base does not export com.sun.javafx.collections to unnamed module @0x4563e9ab
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(Unknown Source)
at java.base/java.security.SecureClassLoader.defineClass(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
at kröw.zeale.v1.program.core.DataManager.<init>(DataManager.java:22)
at kröw.zeale.v1.program.core.DataManager.getDataManager(DataManager.java:63)
at kröw.zeale.v1.program.core.Kröw.<clinit>(Kröw.java:23)
错误中提到的课程Kröw
的一部分:
private static final DataManager DATA_MANAGER = DataManager.getDataManager(); // line 23
错误中提到的类DataManager
的部分:
static DataManager getDataManager() { // line 66
return new DataManager();
}
和
public final ConstructList constructs = new ConstructList(); // line 22
班级ConstructList
:
public class ConstructList extends ObservableListWrapper<Construct> { // line 209
private ConstructList() {
super(new ArrayList<>()); // line 212
}
public LinkedList<Construct> getDeadConstructs() {
...
}
public LinkedList<Construct> getLivingConstructs() {
...
}
}
现在,我已经查看了我可以找到的资源,例如IllegalAccessError SO Question
(注意这说:“试图访问方法”而不是“超类访问检查失败”)
该解决方案的已接受答案是检查编译的jar文件和源代码之间是否有任何不同,所以我尝试了一下,发现了一些细微差别。以下是我的反编译jar文件中更改的代码行。 (使用JD-GUI进行了反编译)
班级DataManager
:
public final ConstructList constructs = new ConstructList(null);
曾经是:
public final ConstructList constructs = new ConstructList();
班级ConstructList
:
private ConstructList() {
super();
}
曾经是:
private ConstructList() {
super(new ArrayList<>());
}
现在,在反编译代码中,ConstructList()
构造函数没有任何参数,我看到它被调用null
被传入,这看起来像是一个错误,但我'我不确定这是否是我的例外的原因,我无法通过互联网找到任何东西,这就是我来到这里的原因。
另一方面,我给出的反编译代码是由我的IDE使用其导出功能创建的。我想看看我的构造函数的null
参数是否存在问题,但我不知道如何以不同的方式编译我的代码以反映这一点。如果有人知道如何更改我收到的导出代码,请通知我。
无论如何,我想知道的是我的代码的哪个部分引起了此异常,以及我如何解决它。
答案 0 :(得分:9)
问题来自Java 9模块系统strongly encapsulates JDK-internal APIs,以及您对JDK内部API的使用,即ObservableListWrapper
(您可以告诉它内部因为包名称开始与com.sun
)。如果您或您的用户通过编译或运行Java 9来使用Java 9,则此错误将持续存在。
正确的解决方法是停止使用ObservableListWrapper
。根据{{3}}判断,您应该使用this presentation (PDF)代替。
如果这对您不起作用,则有一种解决方法。将--add-exports javafx.base/com.sun.javafx.collections=ALL-UNNAMED
添加到编译(javac
)和启动(java
)命令。
答案 1 :(得分:4)
JavaFX is a set of modules in JDK 9, the javadoc is here: http://download.java.net/java/jdk9/jfxdocs/overview-summary.html
从本地路径/服务器路径下载文件javafx.base模块是基础API,如果你看一下javadoc中列出的软件包,你就不会看到com.sun.javafx.collections。这是因为该包是内部的(未导出)到javafx.base模块。 JavaFX之外的任何内容都不应该使用它。您当然可以使用命令行选项来解决此问题,但我认为您必须查看用法以了解它为何尝试使用JavaFX内部类。一旦删除了对内部类的依赖,那么我认为应用程序应该像以前一样工作。
答案 2 :(得分:2)
事实证明,您正在使用Java 9进行编译,后者利用了JDK的新module
系统。可能有一种通过实现模块来解决问题的有效方法,但另一种解决方案是简单地使用Java 8进行编译!
答案 3 :(得分:1)
我想你回答了自己的问题。如果您更新包含细微差别的jar,则错误可能会消失。
答案 4 :(得分:1)
IllegalAccessorError: superclass access check failed
...另一个解决方案是仅使用Java 8进行编译!
通过将Java 11编译器切换为代码级别8 ,然后将public static void main(String[] args ...)
移至非FX类并在那里构建JavaFX Application
),我能够避免这种情况代替。
这行得通吗?这是错误吗?我正在使用AdoptOpenJDK 11进行编译,但使用的是语言级别8。如果没有这种解决方法,则在IntelliJ中会抛出异常,因此如果语言级别8应该自然地抑制了它,那可能只是一个细微差别IDE。