Java,IllegalAccessorError:超类访问检查失败

时间:2017-04-18 03:49:39

标签: java java-9

我一直在用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参数是否存在问题,但我不知道如何以不同的方式编译我的代码以反映这一点。如果有人知道如何更改我收到的导出代码,请通知我。

无论如何,我想知道的是我的代码的哪个部分引起了此异常,以及我如何解决它。

5 个答案:

答案 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。