我遇到了一个奇怪的问题,我无法弄清楚在尝试插入程序时弹出的问题。另一个问题是我无法创建一个简单的测试用例,因为每次尝试都可以。我一定缺少一些并发症。但我会尽力清楚地描述这种情况,以防任何人熟悉。
我有一个称为Seed的基类,它是主应用程序的一部分,并由系统类加载器加载。我有一个包含Road类的插件,该类是Seed的子类。它是在运行时从单独的jar文件加载的。Road类引用字段Seed.garden,该字段定义为:
受保护的最终花园花园;
请注意,我没有得到编译错误。当插件jar包含在系统类路径中时,我也没有得到运行时错误。仅当我的主应用程序使用新的类加载器(以系统类加载器作为其父类)加载插件时,我才会收到错误消息。错误是:
java.lang.IllegalAccessError:试图从类package.Road $ 4访问字段package.Seed.garden
它必须与以下事实有关:子类是由与超类不同的类加载器加载的,但是我找不到任何官方原因说明该子类不起作用。而且,就像我说的那样,当我尝试通过一个简单的测试用例(包括单独的jar,用不同的类加载器加载子类等)重现问题时,我没有收到错误。
我似乎也不太可能违反访问规则,因为当类由同一个类加载器加载时,它可以工作,并且不会出现编译错误。
我没主意了!有谁认识到这个问题,或者对我有一些指导,以指导我寻找方向?救命!
好的,因此在axtavt和其他答复者的帮助下,我弄清楚了问题所在。其他答案有帮助,但他们没有完全正确,这就是为什么我要回答自己的问题。问题原来是“运行时软件包”的概念,在Java虚拟机规范中定义如下:
5.3创建和加载
…在运行时,一个类或接口不是由其名称单独确定的,而是由一个对确定的:其完全限定的名称及其定义的类加载器。每个此类或接口都属于一个运行时包。类或接口的运行时包由包名称以及类或接口的定义类加载器确定。…
5.4.4访问控制
…当且仅当以下任一条件为真时,类或接口D才可以访问字段或方法R:…
第一部分解释了为什么Road被允许访问Seed.garden,因为Road是Seed的子类,而第二部分解释了为什么Road $
4尽管与Road处于同一个包中,却不允许访问它,因为它不是在同一 运行时 包中,由不同的类加载器加载。该限制实际上不是Java语言限制,而是Java
VM限制。
因此,根据我的情况的结论是,由于Java
VM的合法限制而导致发生了异常,因此我将不得不通过将字段公开来解决该问题,因为在这种情况下,这不是问题是最终的,而不是秘密的,或者通过有访问权的Road将Seed.garden导出到Road
$ 4。
谢谢大家的建议和回答!
我正在阅读这本Java SCJP的书,我偶然发现了以下内容: 但是我得到了这个错误: 那么,出什么问题了?
A类源代码: B类源代码: 当我编译B. java时没有错误,当我试图编译A. java时,我得到了: 顺便说一句,我不是用IDE来编译这个,我只是用Geany和nano编辑了文件,然后用javac从终端编译它们。
问题内容: 我想对此进行一些讨论,但无法推断出我的情况的答案。仍然需要帮助。 这是我的代码: 在上面的示例中,下面的一些定义似乎令人困惑: 问题: 为什么我不能从子类实例(对象)访问受保护的成员()? 问题答案: 作为声明类的子类的其他包中的类只能访问其自己的继承成员。 …但不是其他对象的继承成员。
null Child.java ChildTest.java
问题内容: 我想从提供此受保护方法的类的子类中调用另一个实例的受保护方法。请参见以下示例: 告诉我。我看不到这的原因(我以为我已经在其他代码中这样做了)。我想保持此方法的保护,我该怎么办? 编辑 我想提供一个简化的版本,但我没有想到事实是,这些类位于不同的程序包中。 问题答案: 您可以通过子类化和重写来访问受保护的方法。当它们在同一包装中时也是如此。我将添加一些细节。您可以在此处阅读详细信息。 您
问题内容: 我想了解以下示例中的情况(通过包从子类外部访问受保护的成员)。 我知道对于包外部的类,子类只能通过继承才能看到受保护的成员。 有两个包:和。 : : : 可以理解,中的方法可以访问,因为受保护的成员只能通过继承来访问。 我的问题是,为什么是方法,通过在基准访问时,工作正常的方法 ,但 将无法正常工作 通过访问时的参考? 问题答案: 该类中的代码被允许通过type的引用访问受保护的成员。