8

I would like to find or create a Java class loader that loads only system classes, excluding any classes on the application defined class path. My goal is to use that class loader to build a class loader that loads from a specific JAR file, resolving system classes using the system-only class loader, but not contaminating the classes from the JAR file with any classes defined by my application.

So far I have not found any way to create a system-only class loader that does not either use private APIs or make assumptions about the Java implementation. See code below that works in my current environment but makes undesirable assumptions.

If there is no way to create an implementation independent system-only class loader, is there a reason why not? Is what I am trying to do a bad idea?

private ClassLoader createJarClassLoader(File f)
{
    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
    if (systemClassLoader instanceof URLClassLoader) {
        URLClassLoader cl = (URLClassLoader) systemClassLoader;
        URL[] urls = cl.getURLs();
        List<URL> wantedURLs = new ArrayList<>();
        for (URL u : urls) {
            if (isSystemURL(u)) {
                wantedURLs.add(u);
            }
        }
        try {
            wantedURLs.add(f.toURI().toURL());
        } catch (MalformedURLException ex) {
            return null;
        }
        return new URLClassLoader(wantedURLs.toArray(new URL[0]), null);
    }
    return null;
}

private boolean isSystemURL(URL u)
{
    return u.getPath().contains("/jre/");
}
3
  • 2
    why are you trying to do this? what are you trying to acheive? Commented Dec 5, 2015 at 4:30
  • @jtahlborn He gave his reasons very clearly: "My goal is …" Commented Dec 5, 2015 at 12:16
  • 1
    @qqilihq - no, the OP described "what" he was trying to achieve, not "why" Commented Dec 5, 2015 at 15:23

1 Answer 1

1

You need to set the parent ClassLoader to be the bootstrap ClassLoader. Call getClassLoader() on a java.lang.String object to get the bootstrap ClassLoader and use that in your ClassLoader constructor.

public class MyClassLoader extends URLClassLoader {

    protected MyClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    static MyClassLoader getInstance(URL[] urls) {
        ClassLoader parent = "".getClass().getClassLoader();
        return (new MyClassLoader(urls, parent));
    }
}

The representation of the bootstrap classloader is documented as implementation dependent

Some implementations may use null to represent the bootstrap class loader. This method [getClassLoader] will return null in such implementations if this class was loaded by the bootstrap class loader.

but the same wording applies to parent ClassLoader in the ClassLoader constructor, which means that this solution is portable.

Sign up to request clarification or add additional context in comments.

1 Comment

Although it (mostly) works in JDK 8, there is no guarantee that the bootstrap class loader knows about all classes in the Java platform; in the modular JDK planned for JDK9, it definitely will not. The more interesting question is what null means when passed to the ClassLoader constructor. I have found no specification of what it means, but perhaps it could be defined to imply a class loader that knows exactly the classes in the Java platform, no more and no less.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.