在看java和android的類加載機制,途中有一些疑惑,就先記下來。html
jdk和jre是什麼區別? JDK就是Java Development Kit.簡單的說JDK是面向開發人員使用的SDK,它提供了Java的開發環境和運行環境。SDK是Software Development Kit 通常指軟件開發包,能夠包括函數庫、編譯程序等。JRE是Java Runtime Enviroment是指Java的運行環境,是面向Java程序的使用者,而不是開發者。java
rt.jar、dt.jar、tools.jar是什麼? rt.jar這個文件是極爲重要的一個文件,rt是runtime的縮寫,即運行時的意思。是java程序在運行時必不可少的文件。裏面包含了java程序員經常使用的包,如java.lang,java.util,java.io,java.net,java.applet等;dt.jar是關於運行環境的類庫,主要是swing的包,你要用到swing時最好加上;tools.jar 是系統用來編譯一個類的時候用到的,也就是javac的時候用到 。android
lib/
和jre/lib
的區別是什麼? JDK下的lib包括java開發環境的jar包,是給JDK用的,例如JDK下有一些工具,可能要用該目錄中的文件。例如,編譯器等;JDK下的JRE下的lib是開發環境中,運行時須要的jar包。最典型的就是導入的外部驅動jar包。程序員
什麼是android dex文件 明白什麼是 Dex 文件以前,要先了解一下 JVM,Dalvik 和 ART。JVM 是 JAVA 虛擬機,用來運行 JAVA 字節碼程序。Dalvik 是 Google 設計的用於 Android平臺的運行時環境,適合移動環境下內存和處理器速度有限的系統。ART 即 Android Runtime,是 Google 爲了替換 Dalvik 設計的新 Android 運行時環境,在Android 4.4推出。ART 比 Dalvik 的性能更好。Android 程序通常使用 Java 語言開發,可是 Dalvik 虛擬機並不支持直接執行 JAVA 字節碼,因此會對編譯生成的 .class 文件進行翻譯、重構、解釋、壓縮等處理,這個處理過程是由 dx 進行處理,處理完成後生成的產物會以 .dex 結尾,稱爲 Dex 文件。Dex 文件格式是專爲 Dalvik 設計的一種壓縮格式。因此能夠簡單的理解爲:Dex 文件是不少 .class 文件處理後的產物,最終能夠在 Android 運行時環境執行。bootstrap
主要負責加載jdk中的核心類庫,好比rt.jar和其它在jre/lib中的核心類。Bootstrap Class Loader是全部classloader的父加載器。它是有native代碼實現的api
It’s mainly responsible for loading JDK internal classes, typically rt.jar and other core libraries located in $JAVA_HOME/jre/lib directory. Additionally, Bootstrap class loader serves as a parent of all the other ClassLoader instances.app
This bootstrap class loader is part of the core JVM and is written in native code. Different platforms might have different implementations of this particular class loader.jvm
擴展類加載器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)實現的,它負責將 <JAVA_HOME >/lib/ext
或者由系統變量-Djava.ext.dir
指定位置中的類庫 加載到內存中。開發者能夠直接使用標準擴展類加載器。函數
系統類加載器是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)實現的,它負責將用戶類路徑(java -classpath或-Djava.class.path變量所指的目錄,即當前類所在路徑及其引用的第三方類庫的路徑,加載到內存中。開發者能夠直接使用系統類加載器。工具
The system or application class loader, on the other hand, takes care of loading all the application level classes into the JVM. It loads files found in the classpath environment variable, -classpath or -cp command line option. Also, it’s a child of Extensions classloader.
The extension class loader is a child of the bootstrap class loader and takes care of loading the extensions of the standard core Java classes so that it’s available to all applications running on the platform.
Extension class loader loads from the JDK extensions directory, usually $JAVA_HOME/lib/ext directory or any other directory mentioned in the java.ext.dirs system property.
public void printClassLoaders() throws ClassNotFoundException {
System.out.println("Classloader of this class:"
+ PrintClassLoader.class.getClassLoader());
System.out.println("Classloader of Logging:"
+ Logging.class.getClassLoader());
System.out.println("Classloader of ArrayList:"
+ ArrayList.class.getClassLoader());
}
複製代碼
運行結果是
Class loader of this class:sun.misc.Launcher$AppClassLoader@18b4aac2
Class loader of Logging:sun.misc.Launcher$ExtClassLoader@3caeaf62
Class loader of ArrayList:null
classDiagram
Object <|-- ClassLoader
ClassLoader <|-- SecureClassLoader
SecureClassLoader <|-- URLClassLoader
URLClassLoader <|-- ExtClassLoader
URLClassLoader <|-- AppClassLoader
BootStrapClassLoader <-- ExtClassLoader
ExtClassLoader <-- AppClassLoader
AppClassLoader <-- ClassLoaderA
AppClassLoader <-- ClassLoaderB
複製代碼
其中,ExtClassLoader屬於Extension Class Loader,AppClassLoader屬於System Class Loader。
JVM在加載類時默認採用的是雙親委派機制。通俗的講,就是某個特定的類加載器在接到加載類的請求時,首先將加載任務委託給父類加載器,依次遞歸 (本質上就是loadClass函數的遞歸調用)。所以,全部的加載請求最終都應該傳送到頂層的啓動類加載器中。若是父類加載器能夠完成這個類加載請求,就成功返回;只有當父類加載器沒法完成此加載請求時,子加載器纔會嘗試本身去加載。事實上,大多數狀況下,越基礎的類由越上層的加載器進行加載。
加載過程以下:
classDiagram
Object <|-- ClassLoader
ClassLoader <|-- BaseDexClassLoader
ClassLoader <|-- SecureClassLoader
SecureClassLoader <|-- URLClassLoader
BaseDexClassLoader <|-- PathClassLoader
BaseDexClassLoader <|-- DexClassLoader
BaseDexClassLoader <|-- InMemoryDexClassLoader
ClassLoader <|-- BootClassLoader
BootClassLoader <-- PathClassLoader
複製代碼
幾個知識點
A class loader that loads classes from .jar and .apk filescontaining a classes.dex entry. This can be used to execute code notinstalled as part of an application.
SystemServer進程中建立了PathClassLoader,Zygote進程中建立了BootClassLoader,由於app進程是靠Zygote進程fork出來的,那麼app進程中的PathClassLoader是在哪裏建立的?
因而帶着這個問題又研究了一下android api-level 爲28的源代碼,把app中的PathClassLoader的建立過程用時序圖描述出來。
在ActivityThread中ApplicationThread的bindApplication方法中發送消息BIND_APPLICATION給H,H也是ActivityThread的內部類,它繼承了Handler,而後H調用ActivityThread的handleBindApplicationf方法,而後ActivityThread處理該消息時通過層層調用,最後返回了PathClassLoader。
那麼ActivityThread中的ApplicationThread的bindApplication是在何時被誰調用的呢?調用關係以下描述:
能夠看到ActivityThread有個靜態main方法,它通過層層調用而且通過IActivityManager這個IPC操做,調用到了AMS的一些方法,而後AMS再通過IApplicationThread這個IPC操做,調用到了ActivityThread的ApplicationThread的bindApplication方法。
IActivityManager對應的是AMS,IApplicationThread對應的是ActivityThread的ApplicationThread。
ActivityThread的這個靜態main方法是Zygote fork出來app這個子進程後,子進程調用到的。