java – 不能从不同jar中的同一个包访问超类的保护成员

前端之家收集整理的这篇文章主要介绍了java – 不能从不同jar中的同一个包访问超类的保护成员前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个奇怪的问题,我无法弄清楚在尝试插件我的程序时弹出.另外一个问题是我无法创建一个简单的测试用例,因为每次尝试它都可以工作.必须有一些我失踪的并发症.但是,我会尽可能地清楚地描述情况,以防任何人听起来都很熟悉.

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

保护最后花园花园;

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

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

它必须与一个事实有关,这个子类已经被一个不同的类加载器加载超类,但我找不到任何官方的原因,为什么不应该工作.另外,像我说的那样,当我尝试用一​​个简单的测试用例(包括单独的jar,使用不同的类加载器加载子类等)来重现问题时,我没有得到错误.

它似乎也不可能违反访问规则,因为它工作时,类是由同一个类加载器加载,我不会得到编译错误.

我没有想法!有没有人认识到这个问题,还是有一些指向我看的方向?帮帮我!

解决方法

好的,所以在axtavt和其他受访者的帮助下,我想出了什么问题.其他答案有帮助,但他们没有得到正确的,这就是为什么我在回答我自己的问题.问题原来是“运行时包”的概念,在 Java Virtual Machine specification中定义如下:

5.3创建和加载


在运行时,类或接口不是由其名称决定,而是由一对确定:其完全限定名称及其定义的类加载器.每个这样的类或接口属于单个运行时包.类或接口的运行时包由包名称定义并定义类或接口的类加载器.

5.4.4访问控制


当且仅当以下条件为真时,字段或方法R可以由类或接口D访问:…

> R被保护并且在C类中声明,D是C或C本身的子类.
> R是被保护的或者是私有的(即既不是public也不是private,也不是private),并且被同一运行时包中的类声明为D.

第一个条款解释道路是否允许访问Seed.garden,因为Road是Seed的子类,第二个条款解释了为什么Road 4号不允许访问它,尽管与Road相同,因为它不是在同一运行时程序包中,已被不同的类加载器加载.该限制实际上不是Java语言限制,它是Java VM限制.

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

谢谢大家的建议和答案!

猜你在找的Java相关文章