自定义类加载器的流程:
继承:java.lang.ClassLoader
重写findClass方法,首先检查请求的类型是否已经被这个类装载器装载到命名空间中了,如果已经装载,直接返回,如果没有,委派类加载器请求给父类加载器,如果父类加载器能够完成,则返回父类加载器加载的class实例;如果父类加载器不能完成,试图读取该文件目录下该类.class文件,即字节码文件是否有数据,如果获取到数据,则调用defineClass方法导入类型到方法区,如果获取不到对应的字节码或者其他原因失败,返回异常给loadClass,loadClass抛出异常,终止加载过程
强调:被两个类加载器加载的同一个类,jvm不认为是相同的类。
例子:自定义文件系统类加载器,在电脑f:\myjava目录下有HelloWorld.java文件,已经编译执行
package com.test;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 自定义文件系统类加载器
*
* @author pomay
*
*/
public class FileSystemClassLoader extends ClassLoader
{
// 传一个com.pomay.test.HelloWorld -->
// f:/myjava/com/pomay/test/HelloWorld.calss
private String rootDir;
public FileSystemClassLoader(String rootDir)
{
super();
this.rootDir = rootDir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
// 应该先查询有没有加载过该类
Class<?> c = findLoadedClass(name);
// 如果已经加载了该类,直接返回类加载器
if (c != null)
{
return c;
} else// 双亲委派
{
ClassLoader parent = this.getParent();
try
{
c = parent.loadClass(name);
} catch (Exception e)
{
// e.printStackTrace();
}
if (c != null)
{
return c;
} else// 如果父类 加载器没有加载,就读取该文件目录下该类.class文件,即字节码文件是否有数据
{
byte[] classData = getClassData(name);
if (classData == null)// 如果没有读取到数据,抛出异常
{
throw new ClassNotFoundException();
} else
c = defineClass(name, classData, 0, classData.length);
}
}
return c;
}
// 判断该文件目录下该类.class文件,即字节码文件是否有数据
private byte[] getClassData(String className)
{
InputStream is = null;
ByteArrayOutputStream baos = null;
try
{
// 传一个com.pomay.test.HelloWorld -->
// f:/myjava/com/pomay/test/HelloWorld.calss
String path = rootDir + "/" + className.replace(".", "/") + ".class";
is = new FileInputStream(path);
baos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1)
{
baos.write(b, 0, len);
}
return baos.toByteArray();
} catch (IOException e)
{
e.printStackTrace();
return null;
} finally
{
if (baos != null)
{
try
{
baos.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (is != null)
{
try
{
is.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws ClassNotFoundException
{
FileSystemClassLoader loader = new FileSystemClassLoader("F:/myjava");
Class<?> c = loader.findClass("com.pomay.test.HelloWorld");// F:/myjava下的HelloWorld类
Class<?> c1 = loader.findClass("com.pomay.test.MyDemo");// eclipse里com.pomay.test包下的MyDemo类
System.out.println(c.getClassLoader());// com.pomay.test.FileSystemClassLoader@15db9742
System.out.println(c1.getClassLoader());// sun.misc.Launcher$AppClassLoader@73d16e93
}
}