之前讲解过类加载器相关的知识,下面介绍如何自定义一个类加载器
用户自定义类加载器只需要扩展:java.lang.ClassLoader
先看一下ClassLoader的说明部分的示例,如何定义一个从网络上加载class文件
* <p> The network class loader subclass must define the methods {@link
* #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
* from the network. Once it has downloaded the bytes that make up the class,
* it should use the method {@link #defineClass <tt>defineClass</tt>} to
* create a class instance. A sample implementation is:
*
* <blockquote><pre>
* class NetworkClassLoader extends ClassLoader {
* String host;
* int port;
*
* public Class findClass(String name) {
* byte[] b = loadClassData(name);
* return defineClass(name, b, 0, b.length);
* }
*
* private byte[] loadClassData(String name) {
* // load the class data from the connection
* . . .
* }
* }
* </pre></blockquote>
public Class findClass(String name) 这一部分是对应的ClassLoad.loadClass(String name,boolean resolve)中的调用用户自定义实现部分
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);//用户自定义实现部分
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
分析以上代码之后,我们就清楚如何去实现自定义的类加载器了。
package com.test;
import java.io.InputStream;
/**
* 实现一个从磁盘文件中加载Class文件的类加载器
* @author Administrator
*
*/
public class MyClassLoader extends ClassLoader {
private String loaderName;
private String loaderPath;
public MyClassLoader(String loaderName){
super();//将系统类加载器作为parent类加载器 getSystemClassLoader()
this.loaderName=loaderName;
}
public void setLoaderPath(String loaderPath) {
this.loaderPath = loaderPath;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
byte[] data=loadClassData(name);
return this.defineClass(name, data, 0, data.length);
}
/**
* 备注:在windows上测试
*
* @param name
* @return
*/
private byte[] loadClassData(String name) {
//file : this.loaderPath+name+".class"
String fullPath=this.loaderPath+name.replace(".", "//")+".class";
InputStream in=null;
java.io.ByteArrayOutputStream out=null;
try{
in=new java.io.FileInputStream(fullPath);
out=new java.io.ByteArrayOutputStream();
int data=0;
while((data=in.read()) != 0 ){
out.write(data);
}
}catch(Exception ex){
ex.printStackTrace();
}finally{
if( in != null){
try{
in.close();
}catch(Exception ex){}
try{out.close();}catch(Exception ex){}
}
}
return out.toByteArray();
}
}