1.概述
classloader 的作用是加载字节码到jvm,有些情况下,我们比如使用插件模式,可能需要自定义从外部加载插件到jvm。
2.实现过程
2.1.定义自定义classloader
package com.example.demo.loader;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class MyClassLoader extends ClassLoader {private String classPath;public MyClassLoader(String classPath) {this.classPath = classPath;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {byte[] classData = loadClassData(name);if (classData == null) {throw new ClassNotFoundException();} else {return defineClass(name, classData, 0, classData.length);}}private byte[] loadClassData(String className) {// 将包名转换为路径String fileName = classPath + File.separator +className.replace('.', File.separatorChar) + ".class";try (InputStream is = new FileInputStream(fileName);ByteArrayOutputStream baos = new ByteArrayOutputStream()) {int ch;while ((ch = is.read()) != -1) {baos.write(ch);}return baos.toByteArray();} catch (IOException e) {e.printStackTrace();return null;}}
}
这个代码继承 classloader,并重写了findClass.
2.2.定义外部类
package com.example.demo.loader;public class MyDynamicClass {public void sayHello() {System.out.println("Hello from dynamically loaded class!");}
}
2.3. 使用自定义classloader
package com.example.demo.loader;public class ClassLoaderDemo {public static void main(String[] args) {try {// 指向 .class 文件的根目录MyClassLoader loader = new MyClassLoader("D:\\work\\research\\demo\\target\\classes");// 加载类(注意使用全限定名)Class<?> clazz = loader.loadClass("com.example.demo.loader.MyDynamicClass");// 创建实例Object instance = clazz.getDeclaredConstructor().newInstance();// 调用方法clazz.getMethod("sayHello").invoke(instance);} catch (Exception e) {e.printStackTrace();}}
}