Java Class Loader Code Example


Java Class Loader Code Example

Sometimes, client only has interface, need to download class implementation from server. In this case, we need to write our own class loader.

There are 2 ways:

1. In client side, if our class loader has not loaded this class, open a socket to server and read class binary from server. This requires server has server socket to listen connection, and return class binary.


package org.codeexample.classloader.client;

public class NetworkClassLoader extends ClassLoader {

private String host;

private int port;

public NetworkClassLoader(String host, int port) {

super();

this.host = host;

this.port = port;

}

public Class findClass(String className) {

Class result = this.findLoadedClass(className);

if (result != null) {

return result;

}

byte[] b = loadClassData(className);

return defineClass(className, b, 0, b.length);

}

private byte[] loadClassData(String name) {

// create a connection and load the class binary from remote machine

return null;

}

public String getHost() {

return host;

}

public int getPort() {

return port;

}

public static void main(String[] args) throws Exception {

ClassLoader classLoader = new NetworkClassLoader("host", 8080);

Class clazz = Class.forName("invalid", false, classLoader);

Object o = clazz.newInstance();

System.err.println(o);

}

}

2. Another way is that, after server accepts a connection, as a last step, server would return a map which stores binary of all classes client needed.

2.Client would save the map and our class loader would use the map to load remote class binary.

package org.codeexample.classloader.client;

public class NetworkClassLoader2 extends ClassLoader {

private Map codeBytes = new HashMap();

protected Class findClass(String className) throws ClassNotFoundException {

Class result = this.findLoadedClass(className);

if (result != null) {

return result;

}

if (codeBytes.containsKey(className)) {

byte[] code = (byte[]) codeBytes.get(className);

return defineClass(className, code, 0, code.length);

} else {

throw new ClassNotFoundException("Unable to find class "

+ className);

}

}

public Map getCodeBytes() {

return codeBytes;

}

/**

* At the last step, server return code binary, client would call this and

* save this binary

*

* @param codeBytes

*/

public void setCodeBytes(Map codeBytes) {

this.codeBytes = codeBytes;

}

public static void main(String[] args) throws Exception {

ClassLoader classLoader = new NetworkClassLoader2();

// Class clazz = classLoader.loadClass("invalid"); //

// NetworkClassLoader2.class.getName()

// Object o = clazz.newInstance();

// System.err.println(o);

Class clazz = Class.forName("invalid", false, classLoader);

Object o = clazz.newInstance();

System.err.println(o);

}

}

The following is the code that server uses to read class binary.

package org.codeexample.classloader.server;

public class CodeSourceHolder {

private static HashSet classes = new HashSet();

public static void addClass(Class clazz) {

classes.add(clazz);

}

public static void main(String[] args) {

addClass(CodeSourceHolder.class);

Map map = getCodeBytes();

Iterator it = map.keySet().iterator();

while (it.hasNext()) {

String clazz = (String) it.next();

byte[] classBytes = (byte[]) map.get(clazz);

System.out.println(clazz + ", class bytes[" + classBytes.length

+ "]");

}

}

public static Map getCodeBytes() {

Map map = new HashMap();

Iterator it = classes.iterator();

while (it.hasNext()) {

try {

Class type = (Class) it.next();

map.put(type.getName(), getCodeBytes(type));

} catch (IOException e) {

e.printStackTrace();

}

}

return map;

}

private static byte[] getCodeBytes(Class clazz) throws IOException {

String name = clazz.getName();

int lastPoint = name.lastIndexOf('.');

if (lastPoint != -1)

name = name.substring(lastPoint + 1);

String resource = name + ".class";

InputStream is = null;

try {

is = clazz.getResourceAsStream(resource);

byte[] codeSource = new byte[is.available()];

is.read(codeSource, 0, codeSource.length);

return codeSource;

} finally {

if (is != null) {

is.close();

}

}

}

}

The following is sample code to demonstrate how to use class loader.

package org.codeexample.classloader;

public class ClassLoaderExample {

public static void testURLClassLoader(String className) throws Exception {

URLClassLoader loader = new URLClassLoader(new URL[] { new URL(

"http://www.codeexample.com/classes/") });

Class c = loader.loadClass(className);

Object o = c.newInstance();

}

public static void testLoadLocalClass(String className) throws Exception {

URLClassLoader loader = new URLClassLoader(new URL[] { new URL(

"file://D:/ws/my-java/bin/") });

Class c = loader.loadClass(className);

Object o = c.newInstance();

// InterfaceA a = (InterfaceA) o;

// System.err.println(a.helloWorld());

}

public static void testContextLocalClass(String className) throws Exception {

String url = "some URL";

ClassLoader previous = Thread.currentThread().getContextClassLoader();

// Create a class loader using the URL as the codebase

// Use previous as parent class loader to maintain current visibility

ClassLoader current = URLClassLoader.newInstance(new URL[] { new URL(

url) }, previous);

Thread.currentThread().setContextClassLoader(current);

}

}

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)