Posted on 2007-04-18 12:55
久城 阅读(5152)
评论(4) 编辑 收藏 所属分类:
JavaTest
以下是整理后的代码部分,欢迎批评指正。
MyClassLoader.java
/**//*
* @MyClassLoader.java 07/04/17
*
* Copyright Zhao Jiucheng. All rights reserved.
*/
package com.neusoft.classloader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/** *//**
* A class loader is an object that is responsible for loading classes. Given
* the binary name of a class, a class loader should attempt to locate or
* generate data that constitutes a definition for the class. A typical strategy
* is to transform the name into a file name and then read a "class file" of
* that name from a file system.
*
* @version 1.0, 07/04/17
* @author Zhao Jiucheng
*
*/
public class MyClassLoader extends ClassLoader {
// a classpath for search
private static String myClasspath = new String("");
// hashtable that memory the loaded classes
private static Hashtable<String, Class<?>> loadClassHashTable = new Hashtable<String, Class<?>>();
// hashtable that memory the time of loading a class
private static Hashtable<String, Long> loadClassTime = new Hashtable<String, Long>();
// the null constructor
public MyClassLoader() {
}
/** *//**
* create a classloader and specify a classpath.
*
* @param myClasspath
* the specified classpath name.
*/
public MyClassLoader(String myClasspath) {
if (!myClasspath.endsWith("\\")) {
myClasspath = myClasspath + "\\";
}
MyClassLoader.myClasspath = myClasspath;
}
/** *//**
* set the classpath
*
* @param myClasspath
* the specified classpath name
*/
public void SetmyClasspath(String myClasspath) {
if (!myClasspath.endsWith("\\")) {
myClasspath = myClasspath + "\\";
}
MyClassLoader.myClasspath = myClasspath;
}
/** *//**
* Loads the class with the specified binary name. This method searches for
* classes in the same manner as the loadClass(String, boolean) method.
* Invoking this method is equivalent to invoking {loadClass(name,false)}.
*
* @param className
* The binary name of the class.
*
* @return The resulting <tt>Class</tt> object.
*
* @throws ClassNotFoundException
* If the class was not found.
*/
@SuppressWarnings("unchecked")
public Class loadClass(String className) throws ClassNotFoundException {
return loadClass(className, false);
}
/** *//**
* Loads the class with the specified binary name. The default
* implementation of this method searches for classes in the following
* order:
*
* Invoke {findLoadedClass(String)} to check if the class has already been
* loaded.
*
* Invoke {findSystemClass(String)} to load the system class.
*
* Invoke the {findClass(String)} method to find the class.
*
* If the class was found using the above steps, and the resolve flag is
* true, this method will then invoke the {resolveClass(Class)} method on
* the resulting Class object.
*
* @param name
* The binary name of the class.
*
* @param resolve
* If true then resolve the class.
*
* @return The resulting Class object.
*
* @throws ClassNotFoundException
* If the class could not be found.
*/
@SuppressWarnings("unchecked")
protected Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
try {
Class foundClass = findLoadedClass(name);
// check if the class has already been loaded.
if (foundClass != null) {
System.out.println("Complete to load the class: " + name);
return foundClass;
}
// if the class is systemClass, load the system class by system
if (name.startsWith("java.")) {
foundClass = findSystemClass(name);
loadClassHashTable.put(name, foundClass);
System.out.println("System is loading the class: " + name);
return foundClass;
}
// invoke the findClass() method to load the class
try {
foundClass = findClass(name);
} catch (Exception fnfe) {
}
if (resolve && (foundClass != null)) {
resolveClass(foundClass);
}
return foundClass;
} catch (Exception e) {
throw new ClassNotFoundException(e.toString());
}
}
/** *//**
* Finds the class with the specified binary name.The default implementation
* throws a ClassNotFoundException.
*
* @param className
* The binary name of the class.
*
* @return The resulting Class object.
*
* @throws ClassNotFoundException
* If the class could not be found.
*/
@SuppressWarnings("unchecked")
public Class findClass(String className) {
byte[] classData = null;
try {
classData = loadClassData(className);
} catch (IOException e) {
e.printStackTrace();
}
if( classData == null){
return null;
}
System.out.println("MyClassLoader is loading : " + className + "");
Class c = defineClass(className, classData, 0, classData.length);
MyClassLoader.loadClassHashTable.put(className, c);
System.out.println("Complete to load the class :" + className);
return c;
}
/** *//**
* Loads the classData with the specified binary name. This method searches
* for classes in the specified classpath as
* searchFile(myClasspath,className) method.
*
* @param name
* The binary name of the class
*
* @return The resulting the classData of the class object by byte[]
*
* @throws IOException
* if have some failed or interrupted I/O operations.
*/
private byte[] loadClassData(String className) throws IOException {
String filePath = searchFile(myClasspath, className + ".class");
if (!(filePath == null || filePath == "")) {
System.out.println("It have found the file : " + className
+ ". Begin to read the data and load the class。");
FileInputStream inFile = new FileInputStream(filePath);
byte[] classData = new byte[inFile.available()];
inFile.read(classData);
inFile.close();
loadClassTime.put(className, new File(filePath).lastModified());
return classData;
} else {
filePath = searchFile(myClasspath, className + ".java");
if (!(filePath == null || filePath == "")) {
System.out.println("It have found the file : " + filePath
+ ". Begin to translate");
Runtime.getRuntime().exec("javac " + filePath);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Translate it over : " + filePath);
return loadClassData(className);
} else {
System.out
.println("Haven't found the file, and fail to read the classData!");
return null;
}
}
}
/** *//**
* Loads the class with the specified binary name.The default implementation
* throws a ClassNotFoundException.
*
* @param classData
* The data of the class.
* @param className
* The binary name of the class.
*
* @return The resulting Class object.
*
* @throws ClassNotFoundException
* If the class could not be found.
*/
public Class loadClass(byte[] classData, String className)
throws ClassNotFoundException {
System.out.println("MyClassLoader is loading : " + className + "");
Class c = defineClass(className, classData, 0, classData.length);
loadClassHashTable.put(className, c);
System.out.println("Complete to load the class :" + className);
return c;
}
/** *//**
* Loads the class with the specified binary name.The default implementation
* throws a ClassNotFoundException.
*
* @param className
* The binary name of the class.
* @param jarName
* The binary name of the jar that search the class from it.
*
* @return The resulting Class object.
*
* @throws ClassNotFoundException
* If the class could not be found.
*/
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.err.println("error : can't read the file!");
return null;
}
byte[] classData = new byte[(int) entry.getSize()];
System.out
.println("It have found the file : "
+ className
+ ". Begin to read the data and load the class。");
in.read(classData);
return loadClass(classData, className);
}
}
System.out.println("Haven't found the file " + className
+ " in " + jarName + ".jar.");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
System.out.println("Haven't found the jarFile: " + jarName
+ ".jar.");
return null;
}
return null;
}
/** *//**
* Reloads the class with the specified binary name. Needn't have to restart
* JVM then reload the class.
*
* @param className
* The binary name of the class need to reload .
*
* @return The resulting Class object.
*
* @throws ClassNotFoundException
* If the class was not found.
*/
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);
try {
MyClassLoader mc2 = new MyClassLoader(myClasspath);
mc2.loadClass(fileName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
System.out
.println("The class is the newest version , needn't reloading.");
}
return null;
}
/** *//**
* search the file with the specified binary name. Needn't have to restart
* JVM then reload the class.
*
* @param classpath
* the specified path where we search.
* @param fileName
* The binary name of the file that want to search.
*
* @return The resulting file path.
*/
public String searchFile(String classpath, String fileName) {
String cut = fileName.substring(fileName.lastIndexOf('.'), fileName
.length());
String path = fileName.substring(0, fileName.lastIndexOf('.')).replace(
'.', '/')
+ cut;
File f = new File(classpath + path);
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 + File.separator + objects[i])
.isDirectory()) {
String s = searchFile(classpath + objects[i]
+ File.separator, fileName);
if (s == null || s == "") {
continue;
} else {
return s;
}
}
}
}
return null;
};
public static void main(String[] args) {
MyClassLoader c1 = new MyClassLoader(
"E:/javawork/teacher's classloader/bin");
//MyClassLoader c2 = new MyClassLoader(
// "E:/javawork/teacher's classloader");
try {
while (true) {
c1.loadClass("com.neusoft.test.A");
//c2.loadClass("com.neusoft.test.B");
try {
Thread.sleep(300000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyThread.java
/**//*
* @MyThread.java 2007/04/17
*
* Copyright Zhao Jiucheng. All rights reserved.
*
*/
package com.neusoft.classloader;
import java.io.File;
/** *//**
* Create a Thread to watch the specify directory,if new classes haved
* appended,load them.
*
* @author Zhao Jiucheng
* @version 1.0, 2007/04/17
*/
public class MyThread extends Thread {
// for get the classpath
private String filePath;
// instantiation a ClassLoader
private MyClassLoader mcl;
/** *//**
* Constructs a new MyThread for the given path.
*
* @param path
* @return null
*/
public MyThread(String path) {
this.filePath = path;
mcl = new MyClassLoader(path);
}
/** *//**
* Watch pecify directory to search for appended classes time after time.
*
* @param filepath
*
* @return null
* @exception ClassNotFoundException
* if the class could not be found.
*/
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();
}
}
}
}
}
/** *//**
* If this thread was constructed using a separate runnable run object, then
* that runnable object's run method is called;
*
* @return null
* @exception InterruptedException
* if the thread has been interrupted.
*/
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.java
/**//*
* @MyURLClassLoader.java 2007/04/17
*
* Copyright Zhao Jiucheng. All rights reserved.
*
*/
package com.neusoft.classloader;
import java.net.*;
/** *//**
* This class loader is used to load classes and resources from a search path
*
* @author Zhao Jiucheng
* @version 1.0, 2007/04/17
*/
public class MyURLClassLoader extends URLClassLoader {
/** *//**
* Constructs a new URLClassLoader for the given URLs.
*
* @param url
*/
public MyURLClassLoader(URL[] url) {
super(url);
}
/** *//**
* Finds the class with the specified binary name.
*
* @param name
* The binary name of the class
* @return The resulting Class object
*
* @throws ClassNotFoundException
* If the class could not be found
*/
@SuppressWarnings("unchecked")
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仅用于个人学习交流!
目的在于记录个人成长.
所有文字均属于个人理解.
如有错误,望多多指教!不胜感激!