Demo for defining class loaders in Java
import static java.lang.System.out; | |
import java.io.IOException; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
import java.nio.file.Paths; | |
/** | |
* Demo code for http://www.romanenco.com/defining-class-loader-java | |
* Compile and run from command line: | |
* javac CLoaderExample.java | |
* java -cp . CLoaderExample | |
*/ | |
public class CLoaderExample { | |
public static void main(String[] args) throws Exception { | |
out.println("With delegation"); | |
/* | |
* Note | |
* dlc will receive only one call for loadClass | |
* and class loader of Custom is system one | |
*/ | |
final DelegatingCL dcl = new DelegatingCL(); | |
Class<?> c = dcl.loadClass("Custom"); | |
out.println("Class loader of C: " + c.getClassLoader()); | |
Class<?> cParent = c.getSuperclass(); | |
out.println("Class loader of super: " + cParent.getClassLoader()); | |
out.println("With interception"); | |
/* | |
* Note | |
* icl receives loadclass call twice, for Custom and it's parent (java.lang.Object) | |
* Class loader of Custom is icl | |
* Class loader of Object - null - this means bootstrap. | |
*/ | |
final InterceptingCL icl = new InterceptingCL(); | |
Class<?> d = icl.loadClass("Custom"); | |
out.println("Class loader of C: " + d.getClassLoader()); | |
Class<?> dParent = d.getSuperclass(); | |
out.println("Class loader of super: " + dParent.getClassLoader()); | |
} | |
} | |
/** | |
* Delegating class loader does not make any resolutions, just print calls. | |
*/ | |
class DelegatingCL extends ClassLoader { | |
@Override | |
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { | |
out.println("CLoader.loadClass(s, b): " + name + ", " + resolve); | |
return super.loadClass(name, resolve); | |
} | |
@Override | |
protected Class<?> findClass(String name) throws ClassNotFoundException { | |
out.println("CLoader.findClass(s): " + name); | |
return super.findClass(name); | |
} | |
} | |
/** | |
* This class loader delegates to parent all calls, other than for class Custom. | |
*/ | |
class InterceptingCL extends ClassLoader { | |
@Override | |
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { | |
out.println("CLoader.loadClass(s, b): " + name + ", " + resolve); | |
if (name.equals("Custom")) { | |
return readAndDefine(name); | |
} | |
return super.loadClass(name, resolve); | |
} | |
@Override | |
protected Class<?> findClass(String name) throws ClassNotFoundException { | |
out.println("CLoader.findClass(s): " + name); | |
return super.findClass(name); | |
} | |
private Class<?> readAndDefine(String name) { | |
Path path = Paths.get(name + ".class"); | |
byte[] data; | |
try { | |
data = Files.readAllBytes(path); | |
} catch (IOException e) { | |
throw new RuntimeException("Can't read file", e); | |
} | |
return defineClass(name, data, 0, data.length); | |
} | |
} | |
class Custom { | |
public static final int I = 99; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment