IllegalAccessError:class<类名>;无法访问其超级接口

发布于 2024-12-05 08:41:41 字数 732 浏览 0 评论 0原文

我有实现 IAssembly 的 Assembly 类。

时出现以下错误

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

启动应用程序程序集代码

class package.Assembly implements IAssembly {

}

IAssembly

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

}

,IAssembly 存在于两个不同的 jar 中。两个 jar 都由不同的类加载器加载。 Assembly 类在子类加载器中加载,IAssembly 是父类。类加载器使用链接。

在正常情况下,这是有效的。当我使用 cobertura 检测 jar 后运行应用程序时,会发生错误。无需仪器,一切正常。 cobertura 仪器会导致这样的错误吗?或者这是一个等待检测的错误,但使用 cobertura 后,错误很快就会暴露出来。

通过将接口设置为“公共”,错误就会消失。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

萧瑟寒风 2024-12-12 08:41:41

在我看来,即使加载器是链接的,包保护也会因检测和多个类加载器而失败。此 javadoc 位于 java.lang.instrument.Instrumentation 与您的场景没有直接关系,但它确实描述了类似的场景:

代理应注意确保 JAR 不包含除引导类加载器出于检测目的而定义的类或资源之外的任何类或资源。不遵守此警告可能会导致难以诊断的意外行为。例如,假设有一个加载器L,L的委托父加载器是引导类加载器。此外,类 C(由 L 定义的类)中的方法引用非公共访问器类 C$1。如果 JAR 文件包含类 C$1,则对引导类加载器的委托将导致引导类加载器定义 C$1。在此示例中,将引发 IllegalAccessError,这可能会导致应用程序失败。避免此类问题的一种方法是为检测类使用唯一的包名称。

Java 虚拟机规范指定,后续尝试解析 Java 虚拟机之前未成功尝试解析的符号引用始终会失败,并出现与初始解析尝试所引发的相同错误。因此,如果 JAR 文件包含与 Java 虚拟机尝试解析引用失败的类相对应的条目,则解析该引用的后续尝试将失败,并出现与初始尝试相同的错误。

也许检查哪个加载器正在查找您的检测类,并查看是否有办法让 AssemblyIAssembly 从同一个类加载器加载。

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.

GRAY°灰色天空 2024-12-12 08:41:41

我认为您的问题可能是您没有使用 IAssembly 的兼容版本。因此,即使它位于您的类路径中,接口及其实现也不匹配。

如果是类加载器问题,您将收到 NoClassDefFoundError。

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.

隔纱相望 2024-12-12 08:41:41

我将添加导致此错误消息的另外两个原因。

  1. 如果界面的可见性不正确并且您需要将其从 protected 更改为 public 或 privateprotected 或 .... 我知道这不是原因,因为提问者知道看到他的评论。
  2. 在您的 IDE 中,一切都是绿色的,但在您的 OSGI 环境中,您收到此错误。您需要检查该类是否已导出并且不在私有包中。

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文