Posted on 2007-04-06 12:25
久城 閱讀(4470)
評論(1) 編輯 收藏 所屬分類:
JavaTest
參考老師的例子,又在網(wǎng)上看了很多資料,總算自己敲出來一個。保存下先...
自定義ClassLoader的實(shí)現(xiàn):

/** *//**
* classloader single
* @author zhaojiucheng
* @version 1.1
* 新增兩個loadClass的重載方法
* 在1.0的基礎(chǔ)上實(shí)現(xiàn)從指定jar包中加載指定的類文件
*/
package zhao;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
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();


public MyClassLoader()
{

}


/** *//**
* 構(gòu)造自定義的加載器 參數(shù)1:路徑名
*/

public MyClassLoader(String MyClasspath)
{

if (!MyClasspath.endsWith("\\"))
{
MyClasspath = MyClasspath + "\\";
}
this.MyClasspath = MyClasspath;
}


/** *//**
* 設(shè)置加載路徑 參數(shù)1:路徑名
*/

public void SetMyClasspath(String MyClasspath)
{

if (!MyClasspath.endsWith("\\"))
{
MyClasspath = MyClasspath + "\\";
}
this.MyClasspath = MyClasspath;
}


/** *//**
* 查找類并加載 參數(shù)1:文件名 被 loadClass() 調(diào)用
*/

public Class findClass(String name)
{
byte[] classData = null;

try
{
classData = loadClassData(name);

} catch (IOException e)
{
e.printStackTrace();
}
Class c = defineClass(name, classData, 0, classData.length);
loadClassHashTable.put(name, c);
System.out.println("加載" + name + "類成功。");
return c;
}


/** *//**
* 讀取文件字節(jié)碼 參數(shù)1:文件名 被 findClass() 調(diào)用
*/

private byte[] loadClassData(String name) throws IOException
{
String filePath = searchFile(MyClasspath, name + ".class");
System.out.println(filePath);

if (!(filePath == null || filePath == ""))
{
FileInputStream inFile = new FileInputStream(filePath);
byte[] classData = new byte[inFile.available()];
inFile.read(classData);
inFile.close();
return classData;
}
System.out.println("讀取字節(jié)碼失敗。");
return null;
}


/** *//**
* 加載類 參數(shù)1:字節(jié)碼數(shù)組 參數(shù)2:類名
*/
public Class loadClass(byte[] classData, String className)

throws ClassNotFoundException
{
Class c = defineClass(className, classData, 0, classData.length);
loadClassHashTable.put(className, c);
System.out.println("加載" + className + "類成功。");
return c;
}


/** *//**
* 加載類 參數(shù)1:類名
*/

public Class loadClass(String name) throws ClassNotFoundException
{
return loadClass(name, false);
}


/** *//**
* 加載類 參數(shù)1:類名 參數(shù)2:是否分析這個類
*/
protected Class loadClass(String name, boolean resolve)

throws ClassNotFoundException
{
byte[] classData = null;
Class temp = null;
// 如是系統(tǒng)類直接裝載并記錄后返回

if (name.startsWith("java."))
{
temp = findSystemClass(name); // 調(diào)用父類方法
loadClassHashTable.put(name, temp);
System.out.println("loadClass: SystemLoading " + name);
return temp;
}


try
{
temp = findLoadedClass(name);// here need try again it is how to
// work

if (temp != null)
{
System.out.println(name + " have loaded
");
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());
}
}


/** *//**
* 加載類 參數(shù)1:要加載的類名 參數(shù)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)
{
// System.out.println(entry.getName());
String outFileName = entry.getName().substring(
entry.getName().lastIndexOf("/") + 1,
entry.getName().length());
// System.out.println(outFileName);

if (outFileName.equals(className + ".class"))
{

if (entry.getSize() == -1)
{
System.out.println("錯誤:無法讀取該文件!");
return null;
}
byte[] classData = new byte[(int) entry.getSize()];
in.read(classData);
return loadClass(classData, className);
}
}

} catch (IOException e)
{
e.printStackTrace();

} finally
{

try
{
in.close();

} catch (IOException e)
{
e.printStackTrace();
}
}

} else
{
System.out.println("don't find the " + jarName + ".jar");
return null;
}
return null;
}


/** *//**
* 查詢文件 參數(shù)1:路徑名 參數(shù)2:文件名
*/

public String searchFile(String classpath, String fileName)
{
File f = new File(classpath + fileName);
// 測試此路徑名表示的文件是否是一個標(biāo)準(zhǔn)文件

if (f.isFile())
{
return f.getPath();

} else
{
// 返回由此抽象路徑名所表示的目錄中的文件和目錄的名稱所組成字符串?dāng)?shù)組
String objects[] = new File(classpath).list();

for (int i = 0; i < objects.length; i++)
{
// 測試此抽象路徑名表示的文件是否是一個目錄
if (new File(classpath + f.separator + objects[i])

.isDirectory())
{
// 迭代遍歷。separator是與系統(tǒng)有關(guān)的默認(rèn)名稱分隔符
return searchFile(classpath + f.separator + objects[i]
+ f.separator, fileName);
}
}
}
System.out.println("沒有找到文件:" + fileName);
return null;
};


public static void main(String[] args)
{
MyClassLoader cl = new MyClassLoader("e:\\test");

try
{
// 從tools.jar包中加載ContentSigner類
cl.loadClass("ContentSigner", "tools");

} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}

歡迎來訪!^.^!
本BLOG僅用于個人學(xué)習(xí)交流!
目的在于記錄個人成長.
所有文字均屬于個人理解.
如有錯誤,望多多指教!不勝感激!