简体   繁体   中英

java dynamic class loading that avoids java.lang.IllegalAccessError

Oracle JavaDocs explains that IllegalAccessError is

"Thrown if an application attempts to access or modify a field, or to call a method that it does not have access to."

I try to load a class dynamically and I get this exception.

if I understand correctly when you use a classloader to load a class with a private package dynamically IllegalAccessError happens

the class I am trying to load is using

org.xml.sax.helpers.SecuritySupport

which also states in their description in the following 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 that

Unfortunately, we can't load the class using reflection * because the class is package private. And the class has * to be package private so the APIs aren't exposed to other * code that could use them to circumvent security. Thus, * we accept the risk that the direct reference might fail * on some JDK 1.1 JVMs, even though we would never execute * this code in such a case. Sigh...

how can I dynamically load it anyway? I have to get it to work. also if I get an error when I use a classloader, I cannot recover from that, so how can I know in advance that I cannot load this class?

thanks in advance to anyone who helps

The statement “ we can't load the class using reflection because the class is package private ” doesn't make any sense, as can be shown easily:

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");
    }
}

This works flawlessly, printing method overridden by subclass replicated the actual use case of that SecuritySupport class.

However, since that class obviously serves the purpose of allowing a transition between Java 1.1 and Java 1.2, it might be possible that there were such restrictions twenty years ago, when this transition happened.

Your use case, however, is entirely different. You say that you are trying to load a class which “is using org.xml.sax.helpers.SecuritySupport ”, which doesn't imply that it is using said class via Reflection, but as shown above, that doesn't matter anyway. It either case, it would only work, if the class is in the same package, whether you load the class “dynamically” or not.

There are only two possible scenarios.

  1. If the class is truly within the same package, which at runtime implies that it also has been loaded by the same class loader, which would require that is also part of the JRE, if the JRE's org.xml.sax.helpers package defines a SecuritySupport class, then the class can access the class within the same package.

  2. If you are trying to load a class via a different ClassLoader from a different code source, it will not be of that package, even if you'd give it a qualified name of the org.xml.sax.helpers.SomeClass form. If the JRE's org.xml.sax.helpers package happens to define a SecuritySupport class, all non-JRE classes would be in a different package. When it tries to access that class, which is not part of the official API, it doesn't work.

    Note that all standard class loaders follow a delegation model trying to resolve a name through their parent class loader first, which is the reason why they all would prefer the JRE's org.xml.sax.helpers.SecuritySupport class, if there is one. With non-standard class loaders, you could have different, unrelated classes with that qualified name, being in different runtime packages.

In that second scenario, the question arises, why your class is using that class. In 2017, there's rarely a need to differentiate between Java 1.1 and Java 1.2 and the functionality offered by that class is also only relevant for a class within the privileged code source of the JRE (or different code sources with different privileges in general).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM