国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

ClassLoader分析

2019-11-08 02:20:30
字體:
來源:轉載
供稿:網友

序言

最近看了看ClassLoader,網上的博客挺多的,大部分都是你抄我的,我抄你的。在他們的基礎上,自己打算寫一篇,自己對ClassLoader的分析,也就是對現有blog的總結吧。

ClassLoader初始化源碼

在openjdk中可以看到下面的代碼。

public Launcher() { // Create the extension class loader ClassLoader extcl; try { extcl = ExtClassLoader.getExtClassLoader(); } catch (IOException e) { throw new InternalError( "Could not create extension class loader"); } // Now create the class loader to use to launch the application try { loader = AppClassLoader.getAppClassLoader(extcl); } catch (IOException e) { throw new InternalError( "Could not create application class loader"); } // Also set the context class loader for the PRimordial thread. Thread.currentThread().setContextClassLoader(loader); // Finally, install a security manager if requested String s = System.getProperty("java.security.manager"); if (s != null) { SecurityManager sm = null; if ("".equals(s) || "default".equals(s)) { sm = new java.lang.SecurityManager(); } else { try { sm = (SecurityManager)loader.loadClass(s).newInstance(); } catch (IllegalaccessException e) { } catch (InstantiationException e) { } catch (ClassNotFoundException e) { } catch (ClassCastException e) { } } if (sm != null) { System.setSecurityManager(sm); } else { throw new InternalError( "Could not create SecurityManager: " + s); } }}

可以看到在Launcher構造函數的執行過程如下:

通過ExtClassLoader.getExtClassLoader()創建了ExtClassLoader;

通過AppClassLoader.getAppClassLoader(ExtClassLoader)創建了AppClassLoader,并將ExtClassLoader設為AppClassLoader的parent ClassLoader;

通過Thread.currentThread().setContextClassLoader(loader)把AppClassLoader設為線程的上下文 ClassLoader;

JDK默認ClassLoader:

在jdk中默認了3種的ClassLoader:BootStrapClassLoader、ExtensionClassLoader和AppClassLoader。

BootStrapClassLoader:它是最頂層的類加載器,是由C++編寫而成, 已經內嵌到JVM中了。在JVM啟動時會初始化該ClassLoader,它主要用來讀取Java的 核心類庫JRE/lib/rt.jar中所有的class文件,這個jar文件中包含了java規范定義的所有接口及實現。ExtensionClassLoader:它是用來讀取Java的一些擴展類庫,如讀取JRE/lib/ext/*.jar中的包等(這里要注意,有些版本的是沒有ext這個目錄的)。AppClassLoaderBootstrp loader加載完ExtClassLoader后,就會加載AppClassLoader,并且將AppClassLoader的父加載器指定為 ExtClassLoader。AppClassLoader也是用Java寫成的,它的實現類是 sun.misc.Launcher$AppClassLoader,另外我們知道ClassLoader中有個getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要負責加載classpath所指定的位置的類或者是jar文檔,它也是Java程序默認的類加載器。

ClassLoader源碼閱讀

成員變量

private final ClassLoader parent; 父類的加載器,所有的新的變量都必須在它之后,英文: The parent class loader for delegation.Note: VM hardcoded the offset of this field, thus all new fields must be added after it.

private final ConcurrentHashMap parallelLockMap; 當前ClassLoader在并發情況下,一個鎖的的對象。 Maps class name to the corresponding lock object when the current class loader is parallel capable. Note: VM also uses this field to decide if the current class loader is parallel capable and the appropriate lock object for class loading.

private final Map package2cert;

每個包的證書,是個HashTable

private static final Certificate[] nocerts = new Certificate[0];

Shared among all packages with unsigned classes

private final Vector> classes = new Vector<>(); 這個class loader加載的所有類,這些類是從開始被GC到gc結束 The classes loaded by this class loader. The only purpose of this table is to keep the classes from being GC’ed until the loader is GC’ed.

private final ProtectionDomain defaultDomain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), null, this, null);

貌似是讀寫的策略,The “default” domain. Set as the default ProtectionDomain on newly created classes.

private final Set domains;

The initiating protection domains for all classes loaded by this loader

構建函數

私有的構造函數

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; } }

也就是分為當前的ClassLoader是否被加載2種情況:ParallelLoaders.isRegistered(this.getClass())來判斷是否可以并行

保護性的構造函數

protected ClassLoader(ClassLoader parent) { this(checkCreateClassLoader(), parent); } protected ClassLoader() { this(checkCreateClassLoader(), getSystemClassLoader()); }

checkCreateClassLoader():是校驗下創建ClassLoader的權限 parent:是創建ClassLoader的父節點 getSystemClassLoader():是獲取系統的ClassLoader,作為當前節點的父節點 3.loadClass

resolve:在虛擬機中找到一個類二進制,再根據resolve參數判斷Classloader用來鏈接一個類

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. 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) { resolveClass(c); } return c; } }

先進行getClassLoadingLock(以后會詳細分析),然后查找已加載的類,在從父類ClassLoader查找,最后查找Bootstrap的ClassLoader

resolveClass:鏈接指定的類。這個方法給Classloader用來鏈接一個類,如果這個類已經被鏈接過了,那么這個方法只做一個簡單的返回。否則,這個類將被按照 Java?規范中的Execution描述進行鏈接

參照:

http://www.hollischuang.com/archives/199


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 民勤县| 临西县| 方正县| 金秀| 商丘市| 淳化县| 高尔夫| 漯河市| 运城市| 和平县| 光泽县| 鹤壁市| 镇远县| 绥宁县| 洱源县| 红原县| 建瓯市| 阿巴嘎旗| 宁武县| 永胜县| 奉节县| 左权县| 天峨县| 武强县| 格尔木市| 开阳县| 斗六市| 遂平县| 邯郸县| 东乌珠穆沁旗| 凤台县| 宁国市| 滨州市| 怀化市| 正定县| 上思县| 高淳县| 湘乡市| 湛江市| 垫江县| 焦作市|