package com.erwa.jvm;
import java.io.*;
public class MyTest16 extends ClassLoader {
private String classLoaderName ;
private final String fileExtension =".class";
//构造方法
public MyTest16(String classLoaderName){
super();// 将系统类加载器当做该类加载器的父加载器
this.classLoaderName = classLoaderName;
}
public MyTest16(ClassLoader parent,String classLoaderName){
super(parent);// 显示指定该类加载器的父加载器
this.classLoaderName = classLoaderName;
}
@Override
public String toString() {
return "MyTest16{" +
"classLoaderName='" + classLoaderName + '\'' +
", fileExtension='" + fileExtension + '\'' +
'}';
}
@Override
protected Class<?> findClass(String classname) throws ClassNotFoundException {
// 重写findClass
byte[] data = this.loadClassDate(classname);
return this.defineClass(classname, data, 0, data.length);
}
private byte[] loadClassDate(String name){
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = null;
try{
this.classLoaderName = this.classLoaderName.replace(".","http://www.likecs.com/");
is = new FileInputStream(new File(name + this.fileExtension));
baos = new ByteArrayOutputStream();
int ch = 0;
while (-1 != (ch = is.read())) {
baos.write(ch);
}
data = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
assert is != null;
is.close();
assert baos != null;
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return data;
}
public static void test(ClassLoader classLoader) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> clazz = classLoader.loadClass("com.erwa.jvm.MyTest1");
//创建类的实例
Object object = clazz.newInstance();
System.out.println(object);
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
MyTest16 loader1 = new MyTest16("loader1");
test(loader1);
}
}
> 输出结果:
> Task :MyTest16.main()
com.erwa.jvm.MyTest1@6d06d69c
定义的第一个自定义的类加载器结束。
类加载器重要方法详解
启动类加载器
扩展类加载器
应用类加载器
自定义类加载器
拒绝低效率的学习
通过defineClass,将byte转换成Class的对象。
protected final Class<?> defineClass(String name, byte[] b, int off, int len){}
案例结果如下:
类加载器的命名空间
每个类加载器都有 自己的命名空间,命名空间由该加载器及所有父加载器所加载的类组成
子加载器所加载的类能够访问父加载器所加载的类
父加载器加载的类无法访问子加载器所加载的类
在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类
在不同的命名空间中,有可能会出现类的完整名字(包括类的包名)相同的两个类
输出结果一样,说明loader1 和loader2成为了父子关系,在同一命名空间中。
不同类加载器的命名空间关系
类的卸载
类的卸载举例:
也可以通过一个小工具,来查看 jvisualvm