JVM加载类的时候需要一个重要的系统变量——CLASSPATH,CLASSPATH在这里所所描述的就是类加载器,所以类加载器在程序运行的时候基于CLASSPATH,由CLASSPATH负责最终程序类的加载,从而实现整个程序代码加载的流程。
看如下代码:
System.out.println(Person.class.getClassLoader());
System.out.println(Person.class.getClassLoader().getParent());
System.out.println(Person.class.getClassLoader().getParent().getParent());
打印结果:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@42a57993(这是JDK1.8及以前版本,1.9及以后是PlatformClassLoader)
null
这是我们自定义的一个Person类,通过反射获取Person的class文件,然后调用getClassLoader方法去获取当前的类的类加载器。
类加载器是使用的“双亲模式”,也就是说系统类和我们自定义的类的类加载器是不一样的,这是为了保证加载类的时候加载正确,防止恶意代码类和系统类同名后造成恶意加载。
自定义ClassLoader的demo:
public class FileClassLoader extends ClassLoader {
//需要加载class文件路径
private static final String FILE_PATH = "C:" + File.separator + "...";
//这里返回要给class文件,通过class文件根绝反射的概念,我们就可以操作该类对象的方法,构造函数,成员变量等等
public Class<?> loadClassData(String className) throws Exception {
byte[] data = ...;//这里使用IO流获取文件所有字节
//该类表示加载外部的class文件
//第一个参数表示文件路径,
// 第二个参数表示文件的字节数据(可以使用IO流获取文件所有字节)
//第三个参数表示读取字节的开始索引
//第四个参数表示读取字节的结束索引
return super.defineClass(className, data, 0, data.length);;
}
}