下午在看《Java 深度历险》,对Class & ClassLoader的定位不是很clear,于是不小心搜到如下一篇blog:
http://www.cnblogs.com/pony/archive/2008/10/10/1307921.html
blog_name : Java动态加载类 把代码稍作修改,就能跑起来了。ok,now show code:
共4个class--
package com.mark.core.test;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;
public class MyClassLoader extends ClassLoader {
// 定义哈希表(Hashtable)类型的变量,用于保存被载入的类数据。
Hashtable loadedClasses;
public MyClassLoader() {
loadedClasses = new Hashtable();
}
@Override
public synchronized Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class newClass;
byte[] classData;
// 检查要载入的类数据是否已经被保存在哈希表中。
newClass = (Class) loadedClasses.get(className);
// 如果类数据已经存在且resolve值为true,则解析它。
if (newClass != null) {
if (resolve) {
resolveClass(newClass);
}
return newClass;
}
/*
* 首 先 试 图 从 本 地 系 统 类 组 中 载 入 指 定 类。 这 是 必 须 的, 因 为 虚 拟 机 将 这 个 类 载 入 后, 在 解 析 和 执 行 它 时 所 用 到 的 任 何 其 他 类,
* 如java.lang.System 类 等, 均 不 再 使 用 虚 拟 机 的 类 载 入 器, 而 是 调 用 我 们 自 制 的 类 载 入 器 来 加 载。
*/
try {
newClass = findSystemClass(className);
return newClass;
} catch (ClassNotFoundException e) {
System.out.println(className + " is not a system class!");
}
// 如果不是系统类,则试图从网络中指定的URL地址载入类。
try {
// 用自定义方法载入类数据,存放于字节数组classData中。
classData = getClassData(className);
// 由字节数组所包含的数据建立一个class类型的对象。
// newClass = defineClass(classData, 0, classData.length);
newClass = defineClass(null, classData, 0, classData.length);
if (newClass == null) {
throw new ClassNotFoundException(className);
}
} catch (Exception e) {
throw new ClassNotFoundException(className);
}
// 如果类被正确载入,则将类数据保存在哈希表中,以备再次使用。
loadedClasses.put(className, newClass);
// 如果resolve值为true,则解析类数据。
if (resolve) {
resolveClass(newClass);
}
return newClass;
}
// 这个方法从网络中载入类数据。
protected byte[] getClassData(String className) throws IOException {
byte[] data;
int length;
try {
// 从网络中采用URL类的方法载入指定URL地址的类的数据。
URL url = new URL(className.endsWith(".class") ? className : className + ".class");
URLConnection connection = url.openConnection();
InputStream inputStream = connection.getInputStream();
length = connection.getContentLength();
data = new byte[length];
inputStream.read(data);
inputStream.close();
return data;
} catch (Exception e) {
System.out.println("================start:");
e.printStackTrace();
System.out.println("================end:");
throw new IOException(className);
}
}
}
interface:
package com.mark.core.test;
public interface Share {
public void start(String[] option);
}
client test class:
package com.mark.core.test;
public class TestClassLoader {
public static void main(String[] args) {
MyClassLoader ll = new MyClassLoader();
Class cc;
Object oo;
String ss = "http://localhost:8080/webdemo2/classes/RemoteClass.class";
if (args.length != 0) {
ss = args[0];
}
try {
System.out.println("Loading class " + ss + "...");
// 使用重写的方法loadClass()载入类数据。
cc = ll.loadClass(ss);
System.out.println("Creat instance...");
// 创建Object类型的类实例。
oo = cc.newInstance();
System.out.println("Call start() method...");
// 强制类型转换并执行被载入类中的方法。
((Share) oo).start(args);
} catch (Exception e) {
System.out.println("Caught exception : " + e);
e.printStackTrace();
}
}
}
the file below should be deploy in server after compiler it.
package com.mark.core.test;
public class RemoteClass implements Share {
/* (non-Javadoc)
* @see com.mark.core.test.Share#start(java.lang.String[])
*/
@Override
public void start(String[] option) {
System.out.println("congratulations!");
}
}
how to?
step 1: build a java application project [A]. add the code above.
step 2: build a java_server project [B] that it can run on tomcat or other servers.
step 3: in java_server project : then you can copy RemoteClass.class from project A to project B And don't forget to delete the RemoteClass.java in Project A.
step 4:
update code.
String ss = "http://localhost:8080/webdemo2/classes/RemoteClass.class";