Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java, IllegalAccessorError: superclass access check failed

Tags:

java

java-9

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.

like image 943
Kröw Avatar asked Apr 18 '17 03:04

Kröw


5 Answers

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.

like image 65
Nicolai Parlog Avatar answered Nov 08 '22 06:11

Nicolai Parlog


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.

like image 30
Alan Bateman Avatar answered Nov 08 '22 07:11

Alan Bateman


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!

like image 35
Jacob G. Avatar answered Nov 08 '22 06:11

Jacob G.


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

like image 36
aedan Avatar answered Nov 08 '22 08:11

aedan


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.

like image 38
tresf Avatar answered Nov 08 '22 08:11

tresf