類加載運行的全程序
當用java命令運行某個main函式時,首先需要類加載器把主類加載到JVM記憶體中,
通過Java命令執行代碼的大致流程為

將編譯好的位元組碼class檔案通過java命令,在win作業系統就是一個java.exe檔案,這個檔案底層是c++語言實作的,通過這個檔案呼叫底層jvm.dll檔案創建Java虛擬機,這個jvm.dll檔案也是c++語言實作的就是一些類別庫,在創建JVM虛擬機的程序中會通過c++語言創建一個引導類加載器,最終由C++語言呼叫java代碼創建JVM啟動器Launcher,該類由引導類加載器創建其他類加載器,最終呼叫的Launcher類的getLauncher()方法,這個方法創建加載了擴展類加載器,應用程式類加載器,最終呼叫loadClass()方法實作類的加載,這個方法體現了雙親委派機制,
java里面有一下幾種類加載器:
引導類加載器:加載jre/lib下核心jar包 如rt.jar charset.jar
擴展類加載器:加載jre/lib/ext下面的jar包
應用程式類加載器:加載自己寫的java類
自定義類加載器:負責加載用戶自定義路徑下的類包
如果想要擺脫雙親委派機制可以重寫loadclass方法
//ClassLoader的loadClass方法,里面實作了雙親委派機制
2 protected Class<?> loadClass(String name, boolean resolve)
3 throws ClassNotFoundException
4 {
5 synchronized (getClassLoadingLock(name)) {
6 // 檢查當前類加載器是否已經加載了該類
7 Class<?> c = findLoadedClass(name);
8 if (c == null) {
9 long t0 = System.nanoTime();
10 try {
11 if (parent != null) { //如果當前加載器父加載器不為空則委托父加載器加載該類
12 c = parent.loadClass(name, false);
13 } else { //如果當前加載器父加載器為空則委托引導類加載器加載該類
14 c = findBootstrapClassOrNull(name);
15 }
16 } catch (ClassNotFoundException e) {
17 // ClassNotFoundException thrown if class not found
18 // from the non‐null parent class loader
19 }
2021 if (c == null) {
22 // If still not found, then invoke findClass in order
23 // to find the class.
24 long t1 = System.nanoTime();
25 //都會呼叫URLClassLoader的findClass方法在加載器的類路徑里查找并加載該類
26 c = findClass(name);
27
28 // this is the defining class loader; record the stats
29 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 ‐ t0);
30 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
31 sun.misc.PerfCounter.getFindClasses().increment();
32 }
33 }
34 if (resolve) { //不會執行
35 resolveClass(c);
36 }
37 return c;
38 }
39 }
如果想自己定義類加載器,定義要加載自己的類路徑則重新撰寫findClass()方法;
為什么jdk設計者要對類加載實作雙親委派機制?
1.沙箱安全機制 自己寫的java.lang.String.class類不會被加載,這樣便可以防止核心API庫被隨意篡改
2.避免類的重復加載 父類加載過得類,子類沒必要重復加載
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/153772.html
標籤:Java
