1).自定义类加载器只需要继承 java.lang.ClassLoader 类,
该类有两个核心方法,一个是 loadClass(String, boolean),实现了双亲委派机制,
还有一个方法是findClass,默认实现是空 方法,所以我们自定义类加载器主要是重写findClass方法。
2).自定义类加载器示例
package com.tuling.jvm;import java.io.FileInputStream;import java.lang.reflect.Method;public class MyClassLoaderTest {//1.自定义加载器MyClassLoader,继承ClassLoaderstatic class MyClassLoader extends ClassLoader {private String classPath;public MyClassLoader(String classPath) {this.classPath = classPath;}private byte[] loadByte(String name) throws Exception {name = name.replaceAll("\\.", "/");FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");int len = fis.available();byte[] data = new byte[len];fis.read(data);fis.close();return data;}//2.重写ClassLoader中的findClass方法protected Class<?> findClass(String name) throws ClassNotFoundException {try {byte[] data = loadByte(name);//defineClass将一个字节数组转为Class对象,这个字节数组是class文件读取后最终的字节数组。return defineClass(name, data, 0, data.length);} catch (Exception e) {e.printStackTrace();throw new ClassNotFoundException();}}}public static void main(String args[]) throws Exception {//初始化自定义类加载器,会先初始化父类ClassLoader,其中会把自定义类加载器的父加载器设置为应用程序类加载器AppClassLoaderMyClassLoader classLoader = new MyClassLoader("D:/test");//D盘创建 test/com/tuling/jvm 几级目录,将User类丢入该目录Class clazz = classLoader.loadClass("com.tuling.jvm.User");Object obj = clazz.newInstance();Method method = clazz.getDeclaredMethod("sout", null);method.invoke(obj, null);System.out.println(clazz.getClassLoader().getClass().getName());}}
3).User.class类,注意后缀不是.java
package com.tuling.jvm;public class User {public String name;public int age;public User() {}public void sout() {System.out.println("自定义加载器加载了类User并调用了方法sout");}}
4).运行结果:
5).自定义加载器是先从指定的路径进行加载,如果从指定的路径没找到再按照双亲委派机制到app加载器中向上找
