Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IllegalAccessError:class <classname> cannot access its superinterface <interfacename>

I have class Assembly implementing IAssembly.

I see following error when starting the application

Caused by: java.lang.IllegalAccessError: class <Assembly > cannot access its superinterface <IAssembly>
        at java.lang.ClassLoader.defineClass1(Native Method)

Assembly code

class package.Assembly implements IAssembly {

}

IAssembly

interface IAssembly { //note -this is not public, so uses default protected

}

Assembly and IAssembly exists in two different jars. Both jars loaded by different classloaders. The Assembly class is loaded in child classloader, IAssembly is parent. Class loaders are using chaining.

In normal cases, this works. The error occurs when I run my application after instrumenting jars using cobertura. With out instrumentation all works fine. Could cobertura instrumentation cause such error? Or This is an error anyway waiting to be detected, but with cobertura the error is quickly exposed.

By making the interface 'public' the error goes away.

like image 630
Jayan Avatar asked Sep 16 '11 14:09

Jayan


3 Answers

It looks to me like package-protection fails with instrumentation and multiple classloaders, even if the loaders are chained. This javadoc on java.lang.instrument.Instrumentation isn't directly related to your scenario, but it does describe a similar scenario:

The agent should take care to ensure that the JAR does not contain any classes or resources other than those to be defined by the bootstrap class loader for the purpose of instrumentation. Failure to observe this warning could result in unexpected behaviour that is difficult to diagnose. For example, suppose there is a loader L, and L's parent for delegation is the bootstrap class loader. Furthermore, a method in class C, a class defined by L, makes reference to a non-public accessor class C$1. If the JAR file contains a class C$1 then the delegation to the bootstrap class loader will cause C$1 to be defined by the bootstrap class loader. In this example an IllegalAccessError will be thrown that may cause the application to fail. One approach to avoiding these types of issues, is to use a unique package name for the instrumentation classes.

The Java Virtual Machine Specification specifies that a subsequent attempt to resolve a symbolic reference that the Java virtual machine has previously unsuccessfully attempted to resolve always fails with the same error that was thrown as a result of the initial resolution attempt. Consequently, if the JAR file contains an entry that corresponds to a class for which the Java virtual machine has unsuccessfully attempted to resolve a reference, then subsequent attempts to resolve that reference will fail with the same error as the initial attempt.

Maybe check which loader is finding your instrumented classes, and see if there is a way to get both Assembly and IAssembly to load from that same classloader.

like image 72
Byron Hawkins Avatar answered Nov 09 '22 09:11

Byron Hawkins


I think your problem may be that you are not using a compatible version of IAssembly. Thus even though it is in your classpath, the interface and its implementation do not match.

If it was a classloader issue, you would get a NoClassDefFoundError.

like image 45
Robin Avatar answered Nov 09 '22 09:11

Robin


I'll just add two more reasons for this error message

  1. This error could also happen if the visibility of your interface isn't correct and you need to change it from protected to public or private to protected or .... I know it isn't the reason here as the questioner was aware see his comment.
  2. In your IDE everything is green but in your OSGI environment you got this error. You need to check if the class is exported and not in a private package.
like image 29
Christian Avatar answered Nov 09 '22 08:11

Christian