Posted on 2007-04-13 20:59
久城 阅读(459)
评论(0) 编辑 收藏 所属分类:
JavaTest
研究JAVA CLASS LOADING已经好多天了。今天刚刚把代码初步整理了下。等待导师的指点。
MyClassLoader.class文件。
自定义CLASSLOADER类的实现:
/** *//**
* classloader single
* @author zhaojiucheng,liji
* @version 1.2
* 在1.1的基础上实现实现动态Reload
*/
package zhao;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
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.Hashtable;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
/** *//**
* 自定义类加载器
*/
public class MyClassLoader extends ClassLoader {
private static String MyClasspath = new String("");
private static ArrayList loadClassList = new ArrayList();
private static Hashtable loadClassHashTable = new Hashtable();
private static Hashtable loadClassTime = new Hashtable();
public MyClassLoader() {
}
/** *//**
* 构造自定义的加载器 参数1:路径名
*/
public MyClassLoader(String MyClasspath) {
if (!MyClasspath.endsWith("\\")) {
MyClasspath = MyClasspath + "\\";
}
this.MyClasspath = MyClasspath;
}
/** *//**
* 设置加载路径 参数1:路径名
*/
public void SetMyClasspath(String MyClasspath) {
if (!MyClasspath.endsWith("\\")) {
MyClasspath = MyClasspath + "\\";
}
this.MyClasspath = MyClasspath;
}
/** *//**
* 查找类并加载 参数1:文件名 被 loadClass() 调用
*/
public Class findClass(String name) {
byte[] classData = null;
try {
classData = loadClassData(name);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("自定义加载器正在加载: " + name + "");
Class c = defineClass(name, classData, 0, classData.length);
loadClassHashTable.put(name, c);
System.out.println("加载" + name + "类成功。");
return c;
}
/** *//**
* 读取文件字节码 参数1:文件名 被 findClass() 调用
*/
private byte[] loadClassData(String name) throws IOException {
String filePath = searchFile(MyClasspath, name + ".class");
if (!(filePath == null || filePath == "")) {
System.out.println("已经找到" + filePath + ",开始读取字节码并加载。");
FileInputStream inFile = new FileInputStream(filePath);
byte[] classData = new byte[inFile.available()];
inFile.read(classData);
inFile.close();
loadClassTime.put(name, new File(filePath).lastModified());
return classData;
} else {
filePath = searchFile(MyClasspath, name + ".java");
if (!(filePath == null || filePath == "")) {
System.out.println("已经找到" + filePath + "并开始编译");
Runtime.getRuntime().exec("javac " + filePath);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return loadClassData(name);
} else {
System.out.println("未找到类文件,读取字节码失败!");
return null;
}
}
}
/** *//**
* 加载类 参数1:字节码数组 参数2:类名
*/
public Class loadClass(byte[] classData, String className)
throws ClassNotFoundException {
System.out.println("自定义加载器正在加载: " + className + "");
Class c = defineClass(className, classData, 0, classData.length);
loadClassHashTable.put(className, c);
System.out.println("加载" + className + "类成功。");
return c;
}
/** *//**
* 加载类 参数1:类名 类名从当前文件系统中查找指定的Class文件
*/
public Class loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
/** *//**
* 加载类 参数1:类名 参数2:是否分析这个类
*/
protected Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
byte[] classData = null;
Class temp = null;
try {
temp = findLoadedClass(name);
if (temp != null) {
System.out.println(name + "类已被加载!");
return temp;
}
// 如是系统类直接装载并记录后返回
if (name.startsWith("java.")) {
temp = findSystemClass(name);
loadClassHashTable.put(name, temp);
System.out.println("系统正在加载 :" + name);
return temp;
}
try {
temp = findClass(name);
} catch (Exception fnfe) {
}
if (temp == null) {
temp = findSystemClass(name);
}
if (resolve && (temp != null)) {
resolveClass(temp);
}
return temp;
} catch (Exception e) {
throw new ClassNotFoundException(e.toString());
}
}
/** *//**
* 加载类 参数1:要加载的类名 参数2:类所在的jar包名
*/
protected Class loadClass(String className, String jarName)
throws ClassNotFoundException {
String jarPath = searchFile(MyClasspath, jarName + ".jar");
JarInputStream in = null;
if (!(jarPath == null || jarPath == "")) {
try {
in = new JarInputStream(new FileInputStream(jarPath));
JarEntry entry;
while ((entry = in.getNextJarEntry()) != null) {
String outFileName = entry.getName().substring(
entry.getName().lastIndexOf("/") + 1,
entry.getName().length());
if (outFileName.equals(className + ".class")) {
if (entry.getSize() == -1) {
System.out.println("错误:无法读取该文件!");
return null;
}
byte[] classData = new byte[(int) entry.getSize()];
System.out.println("已经找到" + className + ",开始读取字节码并加载。");
in.read(classData);
return loadClass(classData, className);
}
}
System.out.println("没有找到 " + className + " 类文件");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
System.out.println("没有找到 " + jarName + ".jar");
return null;
}
return null;
}
/** *//**
* 参数1:要加载的类名 功能:实现动态Reload 不需要重新启动虚拟机,把新添加的Class文件加载进入JVM,并且替换掉旧的Class文件
*/
public Class reload(String fileName) {
String filePath = searchFile(MyClasspath, fileName + ".class");
Long a = new File(filePath).lastModified();
if (!a.equals(loadClassTime.get(fileName))) {
loadClassHashTable.remove(fileName);
loadClassTime.remove(fileName);
Class temp = null;
try {
MyClassLoader mc2 = new MyClassLoader(MyClasspath);
mc2.loadClass(fileName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
System.out.println("文件未更新。");
}
return null;
}
/** *//**
* 查询文件 参数1:路径名 参数2:文件名
*/
public String searchFile(String classpath, String fileName) {
File f = new File(classpath + fileName);
if (f.isFile()) {
return f.getPath();
} else {
String objects[] = new File(classpath).list();
for (int i = 0; i < objects.length; i++) {
if (new File(classpath + f.separator + objects[i])
.isDirectory()) {
String s = searchFile(classpath + objects[i] + f.separator,
fileName);
if (s == null || s == "") {
continue;
} else {
return s;
}
}
}
}
return null;
};
public static void main(String[] args) {
MyClassLoader cl = new MyClassLoader();
cl.SetMyClasspath("d:\\soft");
try {
while (true) {
//System.out.println("load CTree:");
cl.loadClass("CTree");
cl.reload("CTree");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyThread.java文件。
实现线程监控。循环加载指定目录下的类文件。
package zhao;
import java.io.File;
import java.util.Iterator;
import zhao.MyClassLoader;
public class MyThread extends Thread {
private String filePath;
private MyClassLoader mcl;
public MyThread(String path) {
this.filePath = path;
mcl = new MyClassLoader(path);
}
public void search(String filePath) {
File dir = new File(filePath);
String[] fileList = dir.list();
for (int i = 0; i < fileList.length; i++) {
if (new File(filePath + File.separator + fileList[i]).isDirectory()) {
search(filePath + fileList[i]);
} else if (new File(filePath + File.separator + fileList[i])
.isFile()) {
if (fileList[i].endsWith(".class")) {
try {
mcl.loadClass(fileList[i].substring(0, fileList[i]
.length() - 6));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public void run() {
int i = 1;
while (true) {
search(filePath);
System.out.println("searching " + i++ + "s");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i == 20) {
System.out.println("search over!");
break;
}
}
}
public static void main(String[] args) {
MyThread t = new MyThread("D:\\soft\\aa");
t.start();
}
}
MyURLClassLoader.class文件。
继承URLClassLoader类,实现加载网络上的类。
package zhao;
import java.net.*;
public class MyURLClassLoader extends URLClassLoader {
public MyURLClassLoader(URL[] url) {
super(url);
}
public Class findClass(final String name) {
try {
return super.findClass(name);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
URL url = null;
try {
url = new URL("http://192.168.44.19:8088/WebTest/");
} catch (MalformedURLException e) {
e.printStackTrace();
}
MyURLClassLoader urlClassLoader1 = new MyURLClassLoader(
new URL[] { url });
Class c1 = urlClassLoader1.findClass("Tree");
System.out.println(c1);
}
}
欢迎来访!^.^!
本BLOG仅用于个人学习交流!
目的在于记录个人成长.
所有文字均属于个人理解.
如有错误,望多多指教!不胜感激!