關於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());
}
}