本文將講述如何擴展ClassLoader類實現一個自己的類裝載器,每個Class對象都有一個引用指向裝載他的ClassLoader,你可以通過public ClassLoader getClassLoader()方法得到它。爲了創建自己的類裝載器我們應該擴展ClassLoader類,這是一個抽象類。我們目的是從本地文件系統使用我們實現的類裝載器裝載一個類。我們創建一個FileClassLoader extends ClassLoader。我們需要覆蓋ClassLoader中的
findClass(String name)方法,這個方法通過類的名字而得到一個Class對象。
public Class findClass(String name)
{
byte[] data = loadClassData(name);
return defineClass(name, data, 0, data.length);
}
我們還應該提供一個方法loadClassData(String name),通過類的名稱返回class文件的字節數組。然後使用ClassLoader提供的defineClass()方法我們就可以返回Class對象了。
public byte[] loadClassData(String name)
{
FileInputStream fis = null;
byte[] data = null;
try
{
fis = new FileInputStream(new File(drive + name + fileType));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int ch = 0;
while ((ch = fis.read()) != -1)
{
baos.write(ch);
}
data = baos.toByteArray();
} catch (IOException e)
{
e.printStackTrace();
}
return data;
}
這裏我們是從D盤裝載一個類。
下面我們提供一個類public class MyApp{},類中沒有定義任何方法和變量,下面我們編譯MyApp.java得到MyApp.class,然後把文件放在D盤的根目錄。爲了證明MyApp.class是被我們定義的classloader裝載的,我們在FileClassLoader的main()方法中打印出裝載MyApp.class的類裝載器的名稱。
public static void main(String[] args) throws Exception
{
FileClassLoader loader = new FileClassLoader();
Class objClass = loader.loadClass("MyApp", true);
Object obj = objClass.newInstance();
System.out.println(objClass.getName());
System.out.println(objClass.getClassLoader());
}
編譯FileClassLoader
javac FileClassLoader.java 然後運行java FileClassLoader 可以看到輸出結果爲
MyApp
FileClassLoader@1a5ab41
如果你把MyApp.class放入到你程序的所在目錄會出現什麼情況呢?讀者自己實踐一下吧!下面給出FileClassLoader的源代碼。
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class FileClassLoader extends ClassLoader
{
public static final String drive = "d:/";
public static final String fileType = ".class";
public FileClassLoader() {
super();
}
public FileClassLoader(ClassLoader arg0) {
super(arg0);
}
public Class findClass(String name)
{
byte[] data = loadClassData(name);
return defineClass(name, data, 0, data.length);
}
public byte[] loadClassData(String name)
{
FileInputStream fis = null;
byte[] data = null;
try
{
fis = new FileInputStream(new File(drive + name + fileType));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int ch = 0;
while ((ch = fis.read()) != -1)
{
baos.write(ch);
}
data = baos.toByteArray();
} catch (IOException e)
{
e.printStackTrace();
}
return data;
}
public static void main(String[] args) throws Exception
{
FileClassLoader loader = new FileClassLoader();
Class objClass = loader.loadClass("MyApp", true);
Object obj = objClass.newInstance();
System.out.println(objClass.getName());
System.out.println(objClass.getClassLoader());
}
}