自定义类加载器
/**
* 自定义类加载器
*/
class MyClassLoader extends ClassLoader {
MyClassLoader() {
super();
}
MyClassLoader(ClassLoader parent) {
super(parent);
}
@Override
protected Class<?> findClass(String name) {
String pathStr = "E:\\git\\learn\\target\\classes\\" + name.replace(".", "\\") + ".class";
Path path = Paths.get(pathStr);
/*try (BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(path));
ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) {
byte[] bytes = new byte[1024];
int n = 0;
while ((n = inputStream.read(bytes)) != -1) {
byteOut.write(bytes, 0, n);
}
return defineClass(name, byteOut.toByteArray(), 0, byteOut.size());
} catch (IOException e) {
e.printStackTrace();
}*/
try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) {
Files.copy(path, byteOut);
//注意name是全限定名,否则会抛出NoClassDefFoundError
return defineClass(name, byteOut.toByteArray(), 0, byteOut.size());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
2调用(一)
自定义类加载器继承自系统类加载器,生成的类MyClass1调用系统类加载器加载的MyClass2
public class TestClassLoader {
public static void main(String[] args) throws Exception {
//自定义类加载器继承自系统类加载器
MyClassLoader loader1 = new MyClassLoader(ClassLoader.getSystemClassLoader());
//通过findClass直接加载,而非使用loadClass委托
Class<?> class1 = loader1.findClass("com.zzy.learn.jvm.classloader.MyClass1");
System.out.println("MyClass1的类加载器:" + class1.getClassLoader());
//调用系统类加载器加载的MyClass2
Method method2 = class1.getDeclaredMethod("invokeClass2", MyClass2.class);
method2.invoke(class1.newInstance(), new MyClass2());
}
}
结果
MyClass1的类加载器:com.zzy.learn.jvm.classloader.MyClassLoader@27bc2616
test()
3调用(二)
自定义类加载器继承自启动类加载器(和系统类加载器不在同一分支),生成的类MyClass1调用系统类加载器加载的MyClass2
public class TestClassLoader {
public static void main(String[] args) throws Exception {
//自定义类加载器继承自系统类加载器
MyClassLoader loader1 = new MyClassLoader(null);
//通过findClass直接加载,而非使用loadClass委托
Class<?> class1 = loader1.findClass("com.zzy.learn.jvm.classloader.MyClass1");
System.out.println("MyClass1的类加载器:" + class1.getClassLoader());
//调用系统类加载器加载的MyClass2
Method method2 = class1.getDeclaredMethod("invokeClass2", MyClass2.class);
method2.invoke(class1.newInstance(), new MyClass2());
}
}
结果
MyClass1的类加载器:com.zzy.learn.jvm.classloader.MyClassLoader@27bc2616
Exception in thread "main" java.lang.NoSuchMethodException: com.zzy.learn.jvm.classloader.MyClass1.invokeClass2(com.zzy.learn.jvm.classloader.MyClass2)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at com.zzy.learn.jvm.classloader.TestClassLoader.main(TestClassLoader.java:22)