加載過程當中會先檢查類是否被已加載,檢查順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢查,只要某個classloader已加載就視爲已加載此類,保證此類只全部ClassLoader加載一次。而加載的順序是自頂向下,也就是由上層來逐層嘗試加載此類。緩存
負責加載$JAVA_HOME中jre/lib/rt.jar裏全部的class,由C++實現的核心庫,也就是JVM調用每一個系統的API實現系統功能,實現跨平臺的主要模塊,不是ClassLoader子類。開發者不能直接使用。tomcat
負責加載java平臺中擴展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目錄下的jar包,開發者能夠直接使用。jvm
負責記載classpath中指定的jar包及目錄中class。根據須要,經過class的全限定名來加載類,能夠經過classLoader.getSystemClassLoader()來獲取它。spa
屬於應用程序根據自身須要自定義的ClassLoader,繼承java.lang.classLoader類。如tomcat、jboss都會根據j2ee規範自行實現ClassLoader。線程
defineClass來實現的;而啓動類的加載過程是經過調用 loadClass來實現的。前者稱爲一個類的定義加載器(defining loader),後者稱爲初始加載器(initiating loader)。在 Java 虛擬機判斷兩個類是否相同的時候,使用的是類的定義加載器。也就是說,哪一個類加載器啓動類的加載過程並不重要,重要的是最終定義這個類的加載器。兩種類加載器的關聯之處在於:一個類的定義加載器是它引用的其它類的初始加載器。 Tips:真正完成類的加載工做是經過調用 orm
如類 com.example.Outer引用了類com.example.Inner,則由類 com.example.Outer 的定義加載器負責啓動類 com.example.Inner的加載過程。方法 loadClass()拋出的是 java.lang.ClassNotFoundException 異常;方法 defineClass()拋出的是java.lang.NoClassDefFoundError異常。htm
類加載器在成功加載某個類以後,會把獲得的 java.lang.Class(這裏已經在heap區實例化)類的實例緩存起來。下次再請求加載該類的時候,類加載器會直接使用緩存的類的實例,而不會嘗試再次加載。也就是說,對於一個類加載器(每個類都會有一個加載器)實例來講,相同全名的類只加載一次,即 loadClass方法不會被重複調用。blog
加載: 1. 這裏加載的意思是:每個實例在new 其它的類時,就是一個classloader過程。 2. 這是一個動態過程 Eg:A實例須要實現使用B類的方法b1(): 經過全限名在應用中查找.class文件--->讀取文件到 method Area區(解析一個*.class文件)--->classloader 實例化B一個在Heap區(分配內存),在當前的棧幀中經過B的引用調用b1()--->在當前線程棧中添加一個新的棧幀,同時改變Program counter regsiters的值,指向新棧。(重複這個過程) |