【问题标题】:Java, IllegalAccessorError: superclass access check failedJava,IllegalAccessorError:超类访问检查失败
【发布时间】:2017-04-18 03:49:39
【问题描述】:

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

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

【问题讨论】:

  • 看起来您正在使用 Java 9 进行编译。如果 Java 9 中没有您需要的任何内容,您可以使用 Java 8 对其进行测试吗?
  • 我认为这是因为它试图使用我认为是 JDK 模块之一的javafx.base。希望更改编译器版本可以修复它,因为我对模块几乎一无所知,还没有进一步帮助。
  • 没问题,让我知道会发生什么!如果您还没有 Java 8,则可能需要下载它。
  • 太棒了 :) 我刚刚做到了,谢谢!
  • @YorickIsTheBest 一旦你在 Java 9 上编译或者有人在上面启动你的应用程序,这个问题就会重新出现。请参阅this answer 以获得正确的修复。

标签: java java-9


【解决方案1】:

问题出在Java 9 模块系统strongly encapsulates JDK-internal APIs,以及您使用JDK 内部API,即ObservableListWrapper(您可以说它是内部的,因为包名以com.sun 开头)。如果您或您的用户通过编译或运行 Java 9 来使用 Java 9,此错误将持续存在。

正确的解决方法是停止使用ObservableListWrapper。根据this presentation (PDF) 判断,您应该改用the FXCollections utility class更新FXCollections in OpenJFX 11)。

如果这对您不起作用,则有一种解决方法。将--add-exports javafx.base/com.sun.javafx.collections=ALL-UNNAMED 添加到编译(javac启动(java)命令。

【讨论】:

  • 我还不想构建与 Java 9 兼容的应用程序,因为 Java 9 尚未正式发布,但我不知道 ObservableListWrapper 是内部 API 的一部分,所以我将通过将我当前扩展的类变成一个包装器来解决这个问题。此外,您发给我的一些链接非常有帮助,我不知道 --add-exports 参数,所以谢谢你。
  • FXCollections 链接已损坏。
  • 感谢@tresf,已修复。 :) 以防万一您不知道,您可以编辑任何人的帖子以修复此类错误。
  • "以防万一您不知道,您可以编辑任何人的帖子以修复此类错误。" ...也许我可以,但是当我的声誉低时,小错误被拒绝并建议留下作为cmets。拒绝雄心勃勃的新人是平台可以做的最令人沮丧的事情之一,但规则就是规则。假设该规则没有改变,我将按照指示继续使用该平台。废弃的解决方案最终会得到修复或取代。如果有必要进行细微的更改(遵守规则的证据),我的评论时间戳将作为今后的理由。
  • 我现在正在阅读一些 SO 文章,它们似乎混合在一起......“为编辑辩护”指出......“如果你要编辑帖子,请确保你”重新实质性地改进它。”断开的链接是否属于此类?我不确定。
【解决方案2】:

JavaFX 是 JDK 9 中的一组模块,javadoc 在这里: http://download.java.net/java/jdk9/jfxdocs/overview-summary.html

javafx.base 模块是基础 API,如果您查看 javadoc 中列出的包,您将看不到 com.sun.javafx.collections。这是因为该包是 javafx.base 模块的内部(未导出)。 JavaFX 之外的任何东西都不应该使用它。您当然可以使用命令行选项来解决此问题,但我认为您必须查看用法以了解它为何尝试使用 JavaFX 内部类。一旦消除了对内部类的依赖,我认为应用程序应该像以前一样工作。

【讨论】:

    【解决方案3】:

    事实证明,您正在使用 Java 9 进行编译,它利用了 JDK 的新 module 系统。通过实现模块可能有一种有效的方法来解决您的问题,但是另一种解决方案是简单地使用 Java 8 进行编译!

    【讨论】:

    • 这有帮助,谢谢。有趣的是,在 IntelliJ 中切换到 Java 8 的代码级别还不够,我实际上必须切换到 Java 8 JDK,这并不理想。有趣的是,我可以通过将Application 构造函数移动到一个单独的类中来规避使用Java 8 JDK。我不确定为什么会这样,但似乎有理由进行对话。我已将其作为次要答案发布,以便其他人可以加入 stackoverflow.com/a/58864255/3196753
    【解决方案4】:

    我想你回答了你自己的问题。如果您更新包含细微差异的 jar,该错误可能会消失。

    【讨论】:

    • 我的部分问题是如何做到这一点。我确实认为那会解决它。
    【解决方案5】:

    IllegalAccessorError: superclass access check failed

    ...另一种解决方案是简单地使用 Java 8 进行编译!

    我可以通过将 Java 11 编译器切换到代码级别 8 public static void main(String[] args ...) 移动到非 FX 类并在那里构造我的 JavaFX Application) 来避免这种情况。 p>

    这应该有效吗?这是一个错误吗?我正在使用 AdoptOpenJDK 11 进行编译,但使用的是 Language Level 8。如果没有这种解决方法,异常会在 IntelliJ 中为我抛出,所以 if Language Level 8 应该自然地抑制它,它可能只是一个细微差别IDE 的。

    【讨论】:

    猜你喜欢
    • 2014-11-19
    • 2019-06-13
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    相关资源
    最近更新 更多