13

我有一个奇怪的问题,我无法弄清楚在尝试插件化我的程序时弹出的问题。另一个问题是我无法创建一个简单的测试用例,因为每次我尝试它都有效。一定有一些我错过的并发症。但我会尽量清楚地描述这种情况,以防任何人听起来很熟悉。

我有一个名为 Seed 的基类,它是主应用程序的一部分,由系统类加载器加载。我有一个插件,其中包含一个类 Road,它是 Seed 的子类。它在运行时从一个单独的 jar 文件中加载。Road类引用了Seed.garden字段,定义为:

受保护的最终花园花园;

请注意,我没有收到编译错误。当插件 jar 包含在系统类路径中时,我也不会收到运行时错误。只有当我的主应用程序使用新的类加载器(将系统类加载器作为其父级)加载插件时,我才会收到错误消息。错误是:

java.lang.IllegalAccessError:试图从类 package.Road$4 访问字段 package.Seed.garden

这一定与子类已由与超类不同的类加载器加载这一事实有关,但我找不到任何官方原因说明这不起作用。另外,就像我说的,当我尝试用一​​个简单的测试用例(包括单独的 jar、用不同的类加载器加载子类等)来重现问题时,我没有得到错误。

我似乎也不太可能违反访问规则,因为当类由同一个类加载器加载时它可以工作,并且我没有得到编译错误。

我没主意了!有没有人认识到这个问题,或者有一些指示给我看的方向?帮助!

4

4 回答 4

8

好的,所以在 axtavt 和其他受访者的帮助下,我弄清楚了问题所在。其他答案有所帮助,但他们并没有完全正确,这就是我回答自己问题的原因。问题原来是“运行时包”的概念,在Java 虚拟机规范中定义如下:

5.3 创建和加载

...在运行时,一个类或接口不仅仅由它的名称决定,而是由一对:它的完全限定名称和它的定义类加载器。每个这样的类或接口都属于一个运行时包。类或接口的运行时包由包名和定义类或接口的类加载器决定。...

5.4.4 访问控制

...当且仅当以下任何条件为真时,类或接口 D 才能访问字段或方法 R:...

  • R 是受保护的并在类 C 中声明,而 D 是 C 的子类或 C 本身。
  • R 要么是受保护的,要么是包私有的(即既不是公共的,也不是受保护的,也不是私有的),并且由与 D 相同的运行时包中的类声明。

第一个子句解释了为什么允许 Road 访问 Seed.garden,因为 Road 是 Seed 的子类,第二个子句解释了为什么 Road$4 不允许访问它,尽管它与 Road 在同一个包中,因为它不是在同一个运行时包中,已由不同的类加载器加载。该限制实际上不是 Java 语言限制,而是 Java VM 限制。

因此,我的情况的结论是,由于 Java VM 的合法限制而发生异常,我将不得不解决它,可能通过将字段公开,在这种情况下这不是问题,因为它们是最终的,不是秘密的,或者可能是通过确实可以访问的 Road 将 Seed.garden 导出到 Road$4。

谢谢大家的建议和回答!

于 2012-05-06T11:45:58.907 回答
4

听起来你有一个类身份危机,有两个不同的类加载器在类层次结构中加载同一个类或类似的类。阅读一些关于 java 类加载器的内容。这是一个很好的介绍,“类身份危机”见图2:http ://www.ibm.com/developerworks/java/library/j-dyn0429/

于 2012-05-05T20:48:33.600 回答
1

我应该补充一点,Road$4 是 Road 的匿名内部类...

其他人认为这也是 1998 年的错误:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4116802

除了在封闭类、封闭类或同级类中声明的成员之外,内部类对另一个类的成员的访问权限不比顶级类更大。内部类可以不受限制地访问其封闭类的继承成员,这是一种常见的误解。这不是真的。

我可能会更多地研究这个事实,因为这最初是针对 Java 1.2 报告的,但我似乎从我的阅读中记得今天也是如此。

编辑:

我确认这是真的:

http://docs.oracle.com/javase/tutorial/java/javaOO/summarynested.html

匿名内部类的范围只是它被定义的地方。因此,即使外部类可以访问继承的成员,它也无法访问。

于 2012-05-05T21:48:15.240 回答
0

这是权限错误,因此它取决于您用于运行运行时的框架。只是为了澄清这确实是这样,将父成员公开,然后尝试运行。如果一切正常,然后恢复你的代码,根据你使用的运行时我们需要配置正确的安全访问。

于 2012-05-05T21:33:36.993 回答