NOTE
7.11 自定义类加载器
1. 什么时候需要自定义类加载器 - 加载任意路径(比如非classpath)下的类文件 - 隔离加载类。这样不同应用的同名类都可以加载,比如tomcat 2. 如何自定义类加载器 1. 继承ClassLoader父类 2. 重写父类的方法 1. 如果走双亲委派机制那么重写 findClass 方法
这是历史学习笔记,可能存在过时或不完整的理解。
1. 什么时候需要自定义类加载器
- 加载任意路径(比如非classpath)下的类文件
- 隔离加载类。这样不同应用的同名类都可以加载,比如tomcat
2. 如何自定义类加载器
- 继承ClassLoader父类
- 重写父类的方法
- 如果走双亲委派机制那么重写findClass方法
- 读取类文件的字节码
- 调用父类的defineClass方法加载类
- 如果不走双亲委派机制那么重写loadClass方法
- 如果走双亲委派机制那么重写findClass方法
- 使用者调用类加载器的loadClass方法
3. 例子
- 准备一个Java类,编译成class文件
public class MyClass
{
public MyClass()
{
System.out.println("hello, world!");
}
}
- 自定义类加载器
public class MyClassLoader extends ClassLoader
{
public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException
{
MyClassLoader classLoader = new MyClassLoader();
Class<?> myClass = classLoader.loadClass("MyClass");
Class<?> myClass2 = classLoader.loadClass("MyClass");
System.out.println(myClass == myClass2);//true
myClass.newInstance();//打印hello, world!
MyClassLoader classLoader2 = new MyClassLoader();
Class<?> myClass3 = classLoader2.loadClass("MyClass");
System.out.println(myClass == myClass3);//false.说明类加载器+包名+类名才能唯一确定一个类
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
String path = String.format("C:\\Users\\[user]\\Desktop\\%s.class", name);
try
{
//加载指定路径下的class文件,并转成字节
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Files.copy(Paths.get(path), outputStream);
byte[] bytes = outputStream.toByteArray();
//调用父类的defineClass方法
return defineClass(name, bytes, 0, bytes.length);
}
catch (IOException e)
{
e.printStackTrace();
throw new ClassNotFoundException("类文件没有找到", e);
}
}
}