Java的类加载器自从JDK1.2开始便引入了一条机制,叫做父类委托机制。也就是说,一个类需要被加载的时候,
JVM先会调用他的父类加载器进行加载。如果父类加载器加载不了,再使用其子类进行加载。当然,这类所说的父类加
载器,不一定他们之间是继承的关系,有可能仅仅是包装的关系。不能片面理解。
Java之所以出现这条机制,因为是处于安全性考虑。害怕用户自己定义class文件然后自己写一个类加载器来加载
原本应该是JVM自己加载的类。这样会是JVM虚拟机混乱或者说会影响到用户的安全。
下面我们来自己实现一个类加载器,其中主要就是继承ClassLoader类
package com.bird.classLoad;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class MyClassLoader extends ClassLoader {
private String name; // 类加载器的名字
private String path = "d://"; // 加载类的路径
private final String fileType = ".class"; // .class文件扩展名
public MyClassLoader(String name) {
super();// 让系统加载器成为该类的加载器的父类加载器
this.name = name;
}
public MyClassLoader(ClassLoader parent, String name) {
super(parent); // 显示指定该类加载器的父加载器
this.name = name;
}
@Override
public String toString() {
return this.name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
/**
* 读取class文件作为二进制流放入到byte数组中去
* @param name
* @return
*/
private byte[] loadClassData(String name) {
InputStream in = null;
byte[] data = null;
ByteArrayOutputStream baos = null;
try {
name = name.replace(".", "\\");
in = new BufferedInputStream(new FileInputStream(new File(path
+ name + fileType)));
baos = new ByteArrayOutputStream();
int ch = 0;
while (-1 != (ch = in.read())) {
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return data;
}
/**
* JVM调用的加载器的方法
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] data = this.loadClassData(name);
return this.defineClass(name, data, 0, data.length);
}
public static void main(String[] args) throws Exception {
MyClassLoader loader1 = new MyClassLoader("loader1");
loader1.setPath("d://");
test(loader1);
}
public static void test(ClassLoader loader) throws Exception{
Class<?> clazz = loader.loadClass("com.bird.classLoad.Simple");
Object object = clazz.newInstance();
}
}
protected Class<?> findClass(String name) 这个方法是JVM自己调用的,如果覆盖CLassLoader类,必须覆盖这个方
法才能实现类的加载。然后里面的private byte[] loadClassData(String name) 方法是加载class文件变成二进制文件,
以便加载器完成class的引用。