Posted on 2007-04-18 12:55
久城 阅读(5157)
评论(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仅用于个人学习交流!
目的在于记录个人成长.
所有文字均属于个人理解.
如有错误,望多多指教!不胜感激!