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/");
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With