我有一个名为Seed的基类,它是主应用程序的一部分,由系统类加载器加载.我有一个插件,它包含一个类Road,它是Seed的子类.它在运行时从单独的jar文件加载.课程路线引用了Seed.garden,其定义为:
保护最后花园花园;
请注意,我没有收到编译错误.当插件jar包含在系统类路径中时,我也不会遇到运行时错误.只有当我的主要应用程序使用新的类加载器加载插件(有系统类加载器作为其父代)时,我得到错误.错误是:
java.lang.IllegalAccessError:尝试从类package.Road $4访问字段package.Seed.garden
它必须与一个事实有关,这个子类已经被一个不同的类加载器加载超类,但我找不到任何官方的原因,为什么不应该工作.另外,像我说的那样,当我尝试用一个简单的测试用例(包括单独的jar,使用不同的类加载器加载子类等)来重现问题时,我没有得到错误.
它似乎也不可能违反访问规则,因为它工作时,类是由同一个类加载器加载,我不会得到编译错误.
我没有想法!有没有人认识到这个问题,还是有一些指向我看的方向?帮帮我!
解决方法
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路.
谢谢大家的建议和答案!