1).自定义类加载器只需要继承 java.lang.ClassLoader 类
    该类有两个核心方法,一个是 loadClass(String, boolean),实现了双亲委派机制,
    还有一个方法是findClass,默认实现是空 方法,所以我们自定义类加载器主要是重写findClass方法。

    2).自定义类加载器示例

    1. package com.tuling.jvm;
    2. import java.io.FileInputStream;
    3. import java.lang.reflect.Method;
    4. public class MyClassLoaderTest {
    5. //1.自定义加载器MyClassLoader,继承ClassLoader
    6. static class MyClassLoader extends ClassLoader {
    7. private String classPath;
    8. public MyClassLoader(String classPath) {
    9. this.classPath = classPath;
    10. }
    11. private byte[] loadByte(String name) throws Exception {
    12. name = name.replaceAll("\\.", "/");
    13. FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
    14. int len = fis.available();
    15. byte[] data = new byte[len];
    16. fis.read(data);
    17. fis.close();
    18. return data;
    19. }
    20. //2.重写ClassLoader中的findClass方法
    21. protected Class<?> findClass(String name) throws ClassNotFoundException {
    22. try {
    23. byte[] data = loadByte(name);
    24. //defineClass将一个字节数组转为Class对象,这个字节数组是class文件读取后最终的字节数组。
    25. return defineClass(name, data, 0, data.length);
    26. } catch (Exception e) {
    27. e.printStackTrace();
    28. throw new ClassNotFoundException();
    29. }
    30. }
    31. }
    32. public static void main(String args[]) throws Exception {
    33. //初始化自定义类加载器,会先初始化父类ClassLoader,其中会把自定义类加载器的父加载器设置为应用程序类加载器AppClassLoader
    34. MyClassLoader classLoader = new MyClassLoader("D:/test");
    35. //D盘创建 test/com/tuling/jvm 几级目录,将User类丢入该目录
    36. Class clazz = classLoader.loadClass("com.tuling.jvm.User");
    37. Object obj = clazz.newInstance();
    38. Method method = clazz.getDeclaredMethod("sout", null);
    39. method.invoke(obj, null);
    40. System.out.println(clazz.getClassLoader().getClass().getName());
    41. }
    42. }

    3).User.class类,注意后缀不是.java

    1. package com.tuling.jvm;
    2. public class User {
    3. public String name;
    4. public int age;
    5. public User() {
    6. }
    7. public void sout() {
    8. System.out.println("自定义加载器加载了类User并调用了方法sout");
    9. }
    10. }

    4).运行结果:
    image.png

    5).自定义加载器是先从指定的路径进行加载,如果从指定的路径没找到再按照双亲委派机制到app加载器中向上找