关于ClassLoader 类的javaDoc 分析请点击
结论:
8. 每一个类加载器的实例中都存在着一个与之相关的父类加载器,类加载器加载类或者资源时是通过使用委托机制进行的
9. ClassLoader 默认情况下是被注册支持并行的,如果在层级结构不严谨时,必须要具备并行加载类的能力,否则容易造成死锁
10. 类加载器加载类并非只从文件系统(classpath)下进行加载类,还可以从网络或者应用中构造出来的资源中进行加载,通过defineClass 方法可以将字节数组转化为Class 对象,然后调用该新类型的Class 对象通过调用 Class.newInstance() 创建新的对象
11. 自定义类加载器,通常建议重写findClass 方法,而不是重写loadClass 方法,因为loadClass 方法中实现了委托父类进行类加载的机制
12. 在重写findClass 方法时,获取到类的byte数组后,可以通过调用defineClass 方法获取到Class 对象,再通过class 对象进行实例的创建
/**
* 结论:
* 8. 每一个类加载器的实例中都存在着一个与之相关的父类加载器,类加载器加载类或者资源时是通过使用委托机制进行的
* 9. ClassLoader 默认情况下是被注册支持并行的,如果在层级结构不严谨时,必须要具备并行加载类的能力,否则容易造成死锁
*/
public class ClassLoaderTest3 {
public static void main(String[] args) {
ClassLoader classLoader = ClassLoaderTest3.class.getClassLoader();
System.out.println(classLoader);
ClassLoader classLoaderParent = classLoader.getParent();
System.out.println(classLoaderParent);
}
}
以下是自定义类加载器
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
/**
* 结论:
* 10. 类加载器加载类并非只从文件系统(classpath)下进行加载类,还可以从网络或者应用中构造出来的资源中进行加载,通过defineClass 方法可以将字节数组转化为Class 对象,然后调用该新类型的Class 对象通过调用 Class.newInstance() 创建新的对象
* 11. 自定义类加载器,通常建议重写findClass 方法,而不是重写loadClass 方法,因为loadClass 方法中实现了委托父类进行类加载的机制
* 12. 在重写findClass 方法时,获取到类的byte数组后,可以通过调用defineClass 方法获取到Class 对象,再通过class 对象进行实例的创建
*/
public class ClassLoaderTest4 extends ClassLoader {
private String classPath;//需要加载的类所在目录
private String classLoaderName;
private final String fileExtensionName = ".class";
public ClassLoaderTest4(String classLoaderName,String classPath) {
super();//指定当前类加载器的你加载器为系统类加载器
this.classLoaderName = classLoaderName;
this.classPath = classPath;
}
public ClassLoaderTest4(String classLoaderName, String classPath, ClassLoader parentClassLoader) {
super(parentClassLoader);//指定当前类加载器的父加载器
this.classLoaderName = classLoaderName;
this.classPath = classPath;
}
private byte[] loaderClassData(String binaryName) {
binaryName = binaryName.replace(".","/");
try(
// FileInputStream fis = new FileInputStream(new File(classPath + binaryName+fileExtensionName));
FileInputStream fis = new FileInputStream(classPath + binaryName + fileExtensionName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
){
int read = 0;
while((read = fis.read()) != -1) {
baos.write(read);
}
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected Class findClass(String name) {
System.out.println("ClassLoaderTest4 findClass invoke!");
byte[] bytes = this.loaderClassData(name);
return defineClass(name,bytes,0,bytes.length);
}
public static void main(String[] args) throws Exception {
ClassLoaderTest4 test4 = new ClassLoaderTest4("MyClassLoader1","F:/temp/");
Class<?> aClass = test4.loadClass("com.tanruyu.jvm.classloading.Test0");//loadClass 中如果父加载器不能加载,则会调用子类的findClass 方法进行加载类。
System.out.println(aClass.newInstance());
// Class<?> aClass1 = test4.findClass("com.tanruyu.jvm.classloading.Test0");
// System.out.println(aClass1.newInstance());
}
}