java 類的加載結論三

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


}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章