溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java.lang.ClassLoader與java.net.URLClassLoader學(xué)習(xí)

發(fā)布時(shí)間:2020-07-29 09:31:54 來源:網(wǎng)絡(luò) 閱讀:957 作者:yinyueml 欄目:編程語言

第一部分:java.lang.ClassLoader

類加載器(class loader)用來加載 Java 類到 Java 虛擬機(jī)中。一般來說,Java 虛擬機(jī)使用 Java 類的方式如下:Java 源程序(.java 文件)在經(jīng)過 Java 編譯器編譯之后就被轉(zhuǎn)換成 Java 字節(jié)代碼(.class 文件)。類加載器負(fù)責(zé)讀取 Java 字節(jié)代碼,并轉(zhuǎn)換成 java.lang.Class 類的一個(gè)實(shí)例。每個(gè)這樣的實(shí)例用來表示一個(gè) Java 類。通過此實(shí)例的 newInstance()方法就可以創(chuàng)建出該類的一個(gè)對(duì)象。實(shí)際的情況可能更加復(fù)雜,比如 Java 字節(jié)代碼可能是通過工具動(dòng)態(tài)生成的,也可能是通過網(wǎng)絡(luò)下載的。 基本上所有的類加載器都是 java.lang.ClassLoader 類的一個(gè)實(shí)例

  1. 構(gòu)造函數(shù)

public abstract class ClassLoader
   
private static native void registerNatives();
    static {
        registerNatives();
    }
    
private ClassLoader(Void unused, ClassLoader parent) {
        this.parent = parent;
        if (ParallelLoaders.isRegistered(this.getClass())) {
            parallelLockMap = new ConcurrentHashMap<>();
            package2certs = new ConcurrentHashMap<>();
            domains =
                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
            assertionLock = new Object();
        } else {
            // no finer-grained lock; lock on the classloader instance
            parallelLockMap = null;
            package2certs = new Hashtable<>();
            domains = new HashSet<>();
            assertionLock = this;
        }
    }


2.loadClass方法,該方法為類加載器的主要方法,具體代碼如下:


    

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            //1.異步保護(hù),防止重復(fù)加載同一個(gè)class
        synchronized (getClassLoadingLock(name)) {
            //2.首先,檢查是否類已經(jīng)被加載過了
            Class<?> c = findLoadedClass(name);
            if (c == null) {
            //2.1如果該類未被加載過
                    //2.1.1 System.nanoTime()這個(gè)方法主要是返回一個(gè)系統(tǒng)計(jì)時(shí)器的當(dāng)前值,以毫微秒為單位。但是不能用作來計(jì)算當(dāng)前時(shí)間,只能通過end-start算出間隔時(shí)間
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                    //2.1.2如果有父加載器,即父加載器不為初始加載器,則遞歸父加載器查看是否加載過
                        c = parent.loadClass(name, false);
                    } else {
                    //2.1.3如果沒有父加載器,即父加載器為初始加載器,查找類是否加載,具體看方法
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    //2.1.4如果還是沒有該類,則運(yùn)行findClass方法加載,該方法為虛方法
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
            //解析class,resolve默認(rèn)為false
                resolveClass(c);
            }
            return c;
        }
    }


3.getClassLoadingLock(name)方法

 protected Object getClassLoadingLock(String className) {
        Object lock = this;
        if (parallelLockMap != null) {
            Object newLock = new Object();
            lock = parallelLockMap.putIfAbsent(className, newLock);
            if (lock == null) {
                lock = newLock;
            }
        }
        return lock;
    }




4.findLoadedClass(name)方法

   protected final Class<?> findLoadedClass(String name) {
        if (!checkName(name))
            return null;
        return findLoadedClass0(name);
    }

    private native final Class<?> findLoadedClass0(String name);


5.findBootstrapClassOrNull(name)方法

 private Class<?> findBootstrapClassOrNull(String name)
    {
        if (!checkName(name)) return null;

        return findBootstrapClass(name);
    }

    // return null if not found
    private native Class<?> findBootstrapClass(String name);


6.findClass(name)方法,該方法在ClassLoader中沒有具體實(shí)現(xiàn),因此根據(jù)不同的情況會(huì)重寫該方法進(jìn)行不同情況的判斷。

 protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }

7.resolveClass(Class<?> c)方法

 protected final void resolveClass(Class<?> c) {
        resolveClass0(c);
    }

    private native void resolveClass0(Class<?> c);

8.defineClass方法,主要是將字節(jié)碼class文件進(jìn)行實(shí)例為Class實(shí)例。該方法不可覆蓋,我們在繼承ClassLoader的時(shí)候,會(huì)重寫findClass方法將相關(guān)文件轉(zhuǎn)換成jvm可識(shí)別的Class實(shí)例。必須要在重寫的findClass中調(diào)用defineClass才可以完成轉(zhuǎn)換的邏輯。

    

protected final Class<?> defineClass(String name, byte[] b, int off, int len)
        throws ClassFormatError
    {
        return defineClass(name, b, off, len, null);
    }
 protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                         ProtectionDomain protectionDomain)
        throws ClassFormatError
    {
        protectionDomain = preDefineClass(name, protectionDomain);
        String source = defineClassSourceLocation(protectionDomain);
        Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
        postDefineClass(c, protectionDomain);
        return c;
    }

9.ClassLoader類的相關(guān)測試。



向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI