5

I've been working on a little project of my own in Java, and recently, I compiled it and received this error:

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

Background:

So, I currently have three different classes, all in the same package. My hierarchy is as follows:

• Kröw
• DataManager
   ♦ ConstructList

In previous versions of my program, my hierarchy was like this:

• Kröw
   ♦ DataManager
      - ConstructList

In both cases, ConstructList extended com.sun.javafx.collections.ObservableListWrapper<Construct>. (I don't think that the class Construct is necessary here and I'd rather not show it, but I can if needed.)

Anyways, right now, my IDE can run the application as expected, however, when I export it, the above exception is given to me.

Full Stack Trace:

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)

Part of class Kröw that is mentioned in the error:

private static final DataManager DATA_MANAGER = DataManager.getDataManager(); // line 23

Parts of class DataManager that are mentioned in the error:

static DataManager getDataManager() { // line 66
    return new DataManager();
}

and

public final ConstructList constructs = new ConstructList();  // line 22

Class ConstructList:

public class ConstructList extends ObservableListWrapper<Construct> { // line 209

    private ConstructList() {
        super(new ArrayList<>()); // line 212
    }

   public LinkedList<Construct> getDeadConstructs() {
      ...
   }

   public LinkedList<Construct> getLivingConstructs() {
      ...
   }
}

Now, I have looked at the resources that I could find, such as IllegalAccessError SO Question

(Notice how this said: "tried to access method" instead of "superclass access check failed")

The accepted answer to that solution was to check if anything is different between the compiled jar file and my source code, so I tried that and found some minor differences. Here are the changed lines of code from my decompiled jar file. (Decompiled using JD-GUI)

Class DataManager:

public final ConstructList constructs = new ConstructList(null);

Used to be:

public final ConstructList constructs = new ConstructList();

Class ConstructList:

private ConstructList() {
  super();
}

Used to be:

private ConstructList() {
   super(new ArrayList<>());
}

Now, in the decompiled code, the ConstructList() constructor does not have any parameters, and I see it being invoked with null being passed in, which looks like an error to me, but I'm not sure if it is the cause of my exception and I haven't been able to find anything via the internet, which is why I came here.

On another note, the decompiled code I've given was created by my IDE, using its export function. I would like to see if the null argument with my constructor is the problem, but I do not know how to compile my code in a different way to reflect that. If someone knows how I can change the exported code I am getting, please inform me.

Anyways, what I want to know is what part of my code this exception is caused by, and how I can fix it.

Community
  • 1
  • 1
Kröw
  • 504
  • 2
  • 13
  • 31
  • 2
    It looks like you're compiling with Java 9. If there isn't anything that you require in Java 9, are you able to test it with Java 8? – Jacob G. Apr 18 '17 at 04:13
  • JacobG. Oh. Actually, I didn't know that it was in Java 9. I had that installed to my system a while back but eclipse always compiled using Java 8. I hope... I'll go check eclipse real quick. That might just be the problem. – Kröw Apr 18 '17 at 04:20
  • 2
    I assume it is because it's attempting to use `javafx.base` which I believe is one of the JDK modules. Hopefully changing the compiler version fixes it, as I know next to nothing about modules yet to help any further. – Jacob G. Apr 18 '17 at 04:22
  • @JacobG. I just tried deleting Java 9 from my system manually. Now the jar file has no icon and it can't be opened. I think my system default was set to run all jar files in Java 9. I'm going to try changing that and see if it has any effect. Thanks for your help. – Kröw Apr 18 '17 at 04:36
  • 2
    No problem, let me know what happens! You might have to download Java 8 if you don't already have it as well. – Jacob G. Apr 18 '17 at 04:37
  • @JacobG. I tried running the program in Java 8 and it worked! Thanks for your help. You can submit an answer if you want and I'll accept it. – Kröw Apr 18 '17 at 05:02
  • 2
    Awesome :) and I just did, thanks! – Jacob G. Apr 18 '17 at 05:06
  • 2
    @YorickIsTheBest The problem will resurface as soon as you compile on Java 9 or somebody launches your app on it. See [this answer](http://stackoverflow.com/a/43467136/2525313) for a proper fix. – Nicolai Parlog Apr 18 '17 at 08:23

5 Answers5

12

The problem arises from the Java 9 module system, which strongly encapsulates JDK-internal APIs, and your use of JDK-internal API, namely ObservableListWrapper (you can tell it's internal because the package name starts with com.sun). This error will persist if you or your users use Java 9 either by compiling or running on it.

The proper fix is to stop using ObservableListWrapper. Judging by this presentation (PDF), you should be using the FXCollections utility class (update: FXCollections in OpenJFX 11) instead.

If that doesn't work for you, there is a workaround. Add --add-exports javafx.base/com.sun.javafx.collections=ALL-UNNAMED to the compile (javac) and launch (java) command.

Nicolai Parlog
  • 47,972
  • 24
  • 125
  • 255
  • 1
    I don't want to build my application with Java 9 compatibility just yet, since Java 9 isn't officially out yet, but I did not know that `ObservableListWrapper` was part of the internal API, so I'll make a workaround for that by making my currently extending class into a wrapper, instead. Also, a few of the links you sent me were very helpful, and I did not know about the `--add-exports` argument, so thank you for those. – Kröw Apr 18 '17 at 10:51
  • 1
    The `FXCollections` link is broken. – tresf Nov 14 '19 at 15:53
  • Thanks @tresf, fixed it. :) Just in case you didn't know, you can edit anybody's posts to fix such mistakes. – Nicolai Parlog Nov 25 '19 at 05:56
  • "Just in case you didn't know, you can edit anybody's posts to fix such mistakes." ... Maybe I can, but when my reputation was low, small mistakes were rejected and recommended to be left as comments. Rejection to ambitious newcomers is one of the most disheartening things a platform can do, but rules are rules. Assuming that rule hasn't changed, I will continue using the platform as instructed. Abandoned solutions will eventually get repaired or superceded. My comment timestamp would serve as justification down the road if a minor change was warranted (evidence of following the rules). – tresf Nov 26 '19 at 07:29
  • I'm reading a few SO articles now and they seem to be mixed... "In Defense of Editing" states... "If you are going to edit a post, make sure you’re substantively improving it." Does a broken link fall into this category? I'm not sure. – tresf Nov 26 '19 at 07:43
  • Here's an example of a rejected, minor change: https://stackoverflow.com/review/suggested-edits/15980848. – tresf Nov 26 '19 at 07:48
  • And another: https://stackoverflow.com/review/suggested-edits/14479405 – tresf Nov 26 '19 at 07:51
  • Weird, I think those edits (and particularly fixing link rot) are improvements worth making. – Nicolai Parlog Nov 26 '19 at 18:30
4

JavaFX is a set of modules in JDK 9, the javadoc is here: http://download.java.net/java/jdk9/jfxdocs/overview-summary.html

The javafx.base module is the base APIs and if you look at the packages listed in the javadoc then you won't see com.sun.javafx.collections. This is because that package is internal (not-exported) to the javafx.base module. Nothing outside of JavaFX should be using it. You can of course use command line options to workaround this but I think you have to look at the usage to understand why it's trying to use a JavaFX internal class. Once the dependency on the internal class is removed then I assume the application should work as before.

Alan Bateman
  • 5,283
  • 1
  • 20
  • 25
2

It turns out you were compiling with Java 9 which utilizes the JDK's new module system. There is probably a valid way to fix your problem by implementing modules, however another solution is to simply compile with Java 8!

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • This helped, thanks. Interestingly enough, switching to Java 8's code level in IntelliJ wasn't enough, I had to actually switch to a Java 8 JDK, which is not ideal. Interestingly, I was able to circumvent using the Java 8 JDK by moving the `Application` constructor into a separate class. I'm not sure why this works but it seems reason for a conversation. I've posted it as a secondary answer so others can chime in https://stackoverflow.com/a/58864255/3196753. – tresf Nov 14 '19 at 19:21
1

I think you answered your own question. The error will be probably gone if you update your jar containing the minor differences.

aedan
  • 209
  • 4
  • 12
1

IllegalAccessorError: superclass access check failed

... another solution is to simply compile with Java 8!

I was able to avoid this by switching my Java 11 compiler to Code Level 8 and moving public static void main(String[] args ...) to a non-FX class and constructing my JavaFX Application) there instead.

Should this work? Is this a bug? I'm compiling with AdoptOpenJDK 11, but using Language Level 8. Without this workaround, the exception is throwing for me inside IntelliJ, so if Language Level 8 should naturally suppress it, it may simply be a nuance of the IDE.

Community
  • 1
  • 1
tresf
  • 7,103
  • 6
  • 40
  • 101
  • 1
    This is a known work around discussed here: http://mail.openjdk.java.net/pipermail/openjfx-dev/2018-June/021977.html – matt Dec 13 '19 at 11:05