java动态类加载,避免java.lang.IllegalAccessError

时间:2017-06-23 15:49:15

标签: java classloader dynamic-loading

Oracle JavaDocs解释说IllegalAccessError是

  

“如果应用程序尝试访问或修改字段,则抛出   调用一个它无权访问的方法。“

我尝试动态加载一个类,我得到了这个异常。

如果我在使用类加载器动态加载具有私有包的类时正确理解IllegalAccessError

我正在尝试加载的类正在使用

  

org.xml.sax.helpers.SecuritySupport

在其描述中也在下面的url中说明 http://grepcode.com/file/repository.springsource.com/org.apache.xmlcommons/com.springsource.org.apache.xmlcommons/1.3.4/org/xml/sax/helpers/SecuritySupport.java

  

不幸的是,我们无法使用反射加载类          *因为该类是包私有的。而且班上有          *为私有包,因此API不会暴露给其他人          *可以使用它们来规避安全性的代码。从而,          *我们接受直接引用可能失败的风险          *在一些JDK 1.1 JVM上,即使我们永远不会执行          *在这种情况下这个代码。叹息...

我怎样才能动态加载它?我必须得到它的工作。 如果我在使用类加载器时遇到错误,我也无法从中恢复,所以我怎么能提前知道我无法加载这个类呢?

提前感谢任何帮助

的人

1 个答案:

答案 0 :(得分:2)

语句“我们无法使用反射加载类,因为类是包私有”没有任何意义,因为可以很容易地显示:

package somepackage;

class BaseClass {
    public static void main(String[] args) throws ReflectiveOperationException {
        BaseClass obj=(BaseClass)
            Class.forName("somepackage.SubClass").newInstance();
        obj.aMethod();
    }

    void aMethod() {
        System.out.println("base class");
    }
}
class SubClass extends BaseClass {
    @Override
    void aMethod() {
        System.out.println("method overridden by subclass");
    }
}

这完美无缺,打印method overridden by subclass复制了SecuritySupport类的实际用例。

但是,由于该类显然是为了允许Java 1.1和Java 1.2之间的转换,所以二十年前,当这种转换发生时,可能存在这样的限制。

但是,您的用例完全不同。你说你正在尝试加载一个“正在使用org.xml.sax.helpers.SecuritySupport”的类,这并不意味着它正在通过Reflection使用所述类,但如上所示,无论如何都无关紧要。无论是哪种情况,它都可以工作,如果类在同一个包中,是否“动态”加载类。

只有两种可能的情况。

  1. 如果该类真正位于同一个包中,那么在运行时它意味着它也已被同一个类加载器加载,这也需要它也是JRE的一部分,如果JRE的{{1} } package定义了一个org.xml.sax.helpers类,然后类可以访问同一个包中的类。

  2. 如果您尝试通过不同的SecuritySupport从不同的代码源加载一个类,它将不属于该包,即使您为其提供了{{{ 1}}形式。如果JRE的ClassLoader包恰好定义了org.xml.sax.helpers.SomeClass类,则所有非JRE类都将位于不同的包中。当它试图访问那个不属于官方API的类时,它不起作用。

    请注意,所有标准类加载器都遵循委托模型,首先尝试通过其父类加载器解析名称,这就是为什么他们都希望JRE的org.xml.sax.helpers类(如果有)的原因。对于非标准类加载器,您可以使用具有该限定名称的不同的,不相关的类,位于不同的运行时包中。

  3. 在第二种情况下,问题出现了,为什么你的班级正在使用该类。在2017年,很少需要区分Java 1.1和Java 1.2,并且该类提供的功能也仅与JRE的特权代码源(或其他代码源)中的相关。一般来说不同的特权。)