Created
January 24, 2015 05:27
-
-
Save dcshock/0c3e9400301c733cc711 to your computer and use it in GitHub Desktop.
Child First ClassLoader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.io.InputStream; | |
import java.net.URL; | |
import java.net.URLClassLoader; | |
import java.util.ArrayList; | |
import java.util.Enumeration; | |
import java.util.Iterator; | |
import java.util.List; | |
public class ChildFirstClassLoader extends URLClassLoader { | |
private ClassLoader system; | |
public ChildFirstClassLoader(URL[] classpath, ClassLoader parent) { | |
super(classpath, parent); | |
system = getSystemClassLoader(); | |
} | |
@Override | |
protected synchronized Class<?> loadClass(String name, boolean resolve) | |
throws ClassNotFoundException { | |
// First, check if the class has already been loaded | |
Class<?> c = findLoadedClass(name); | |
if (c == null) { | |
try { | |
// checking local | |
c = findClass(name); | |
} catch (ClassNotFoundException e) { | |
// checking parent | |
// This call to loadClass may eventually call findClass | |
// again, in case the parent doesn't find anything. | |
try { | |
c = super.loadClass(name, resolve); | |
} catch (ClassNotFoundException e2) { | |
if (system != null) { | |
// checking system: jvm classes, endorsed, cmd classpath, | |
// etc. | |
c = system.loadClass(name); | |
} | |
} | |
} | |
} | |
if (resolve) | |
resolveClass(c); | |
return c; | |
} | |
@Override | |
public URL getResource(String name) { | |
URL url = findResource(name); | |
if (url == null) | |
url = super.getResource(name); | |
if (url == null && system != null) | |
url = system.getResource(name); | |
return url; | |
} | |
@Override | |
public Enumeration<URL> getResources(String name) throws IOException { | |
/** | |
* Similar to super, but local resources are enumerated before parent | |
* resources | |
*/ | |
Enumeration<URL> systemUrls = null; | |
if (system != null) { | |
systemUrls = system.getResources(name); | |
} | |
Enumeration<URL> localUrls = findResources(name); | |
Enumeration<URL> parentUrls = null; | |
if (getParent() != null) { | |
parentUrls = getParent().getResources(name); | |
} | |
final List<URL> urls = new ArrayList<URL>(); | |
if (localUrls != null) { | |
while (localUrls.hasMoreElements()) { | |
URL local = localUrls.nextElement(); | |
urls.add(local); | |
} | |
} | |
if (systemUrls != null) { | |
while (systemUrls.hasMoreElements()) { | |
urls.add(systemUrls.nextElement()); | |
} | |
} | |
if (parentUrls != null) { | |
while (parentUrls.hasMoreElements()) { | |
urls.add(parentUrls.nextElement()); | |
} | |
} | |
return new Enumeration<URL>() { | |
Iterator<URL> iter = urls.iterator(); | |
public boolean hasMoreElements() { | |
return iter.hasNext(); | |
} | |
public URL nextElement() { | |
return iter.next(); | |
} | |
}; | |
} | |
@Override | |
public InputStream getResourceAsStream(String name) { | |
URL url = getResource(name); | |
try { | |
return url != null ? url.openStream() : null; | |
} catch (IOException e) { | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This triggers a
SecurityException
when the loader tries to loadjava.lang
.Maybe it should also catch
SecurityException
to fallback first on parent, then on system ?https://gist.github.com/reda-alaoui/a3030964293268eca48ddc66d8a07d74