Created
November 17, 2016 19:59
-
-
Save andrewromanenco/290b6b4ad8111496eebf36f8e1e991f3 to your computer and use it in GitHub Desktop.
Demo for defining class loaders in Java
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 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