先准备一个正确的class文件:
先在E:\Temp\javatest目录写了一个简单的java文件并生成一个合法的class文件:
javaDemo:
/**
* 2021年4月1日下午5:06:10
*/
package testClsLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* @author XWF
*
*/
public class TestClsLoader {
/**
* @param args
*/
public static void main(String[] args) {
try {
MyClsLoader mcl = new MyClsLoader("E:\\Temp\\javatest");
Class<?> cls = mcl.loadClass("Add");
Object obj = cls.getDeclaredConstructor(null).newInstance(null);
Method m = cls.getDeclaredMethod("add", int.class, int.class);
m.invoke(obj, 1, 2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyClsLoader extends ClassLoader {
private String path;
public MyClsLoader(String classFilePath) {
this.path = classFilePath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] bytes = null;
try(FileInputStream fis = new FileInputStream(new File(this.path, name + ".class"))) {
bytes = fis.readAllBytes();
}
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
}
执行结果:
继承ClassLoader重写findClass方法,将.class文件读取放到byte数组,传递给defineClass方法生成Class对象,然后使用反射调用方法即可;
一个classLoader对同一个类只能加载一次,若要动态加载,只需新new一个类加载器重新加载即可,旧实例等gc回收,要注意防止存在引用造成内存泄漏;