自定义类加载器
1、继承 java.lang.ClassLoader
2、检查加载的类是否已经被装载,若已经装载,直接返回
3、委派类加载请求给父类加载器,若父类能完成,返回父类加载器加载的Class实例
4、调用本类加载器findClass方法,试图获取对应字节码,若成功则调用defineClass导入类型到方法区,失败则返回异常。
import java.io.*;
//继承 java.lang.ClassLoader
public class FileSystemClassLoader extends ClassLoader {
private String rootDir;
public FileSystemClassLoader(String rootDir){
this.rootDir = rootDir;
}
//findClass方法
@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){
}
if (c!=null){
return c;
}else {
//获取对应字节数组
byte[] classData = getClassData(name);
if (classData == null){
throw new ClassNotFoundException();
}else{
//利用defineClass导入类型到方法区
c=defineClass(name,classData,0,classData.length);
}
}
}
return c;
}
//获取字节数组对应方法
private byte[] getClassData(String name){
String path = rootDir+"/"+name.replace('.','/')+".class";
InputStream is = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
is = new FileInputStream(path);
byte[] flush = new byte[1024];
int len ;
while((len = is.read(flush))!=-1){
baos.write(flush,0,len);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return null;
}finally {
try {
if (is!=null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
测试:同一个类被不同加载器加载,jvm认为是不同的
public static void main(String[] args) throws ClassNotFoundException {
FileSystemClassLoader loader = new FileSystemClassLoader("D:/JavaNote");
FileSystemClassLoader loader02 = new FileSystemClassLoader("D:/JavaNote");
Class<?> c = loader.loadClass("Test");
Class<?> c2 = loader.loadClass("Test");
Class<?> c3 = loader02.loadClass("Test");
Class<?> c4 = loader.loadClass("java.lang.String");
Class<?> c5 = loader.loadClass("Re.Test");
System.out.println(c.hashCode());
System.out.println(c2.hashCode()); //与c相同
System.out.println(c3.hashCode()); //与c、c2相同,同一个类被不同加载器加载,jvm认为是不同的
System.out.println(c4.hashCode());
System.out.println(c5.getClassLoader()); //系统默认加载器
System.out.println(c3.getClassLoader()); //自定义加载器
System.out.println(c4.getClassLoader()); //null 引导类加载器
}