-
JVM
jvm是jre里頭一個動態(tài)連接函數(shù)庫,jdk里面的jre一般用于運行java本身的程序,比如javac,等等.programfiles下面的jre用于運行用戶編寫的java程序.
JRE下的bin\client 或者 bin\server 的jvm.dll就是JVM了
當一臺機器上有多個jvm可選擇的時候,jvm的選擇步驟:
1)當前目錄有沒有jre目錄(不準確),
2)父目錄下的jre子目錄
3)注冊表HEKY_LOCAL_MACHINE\SoftWare\Java\Java Runtime Environment\
所以當運行的是jdk\bin\java.exe的時候,用的jre是bin的父目錄jdk下面的jre\
運行java.exe找到了jre后有一個驗證程序,驗證jre和java.exe的版本是否一致,如果不一致則會發(fā)生錯誤
- java -verbose:class Main 顯示調(diào)用的詳細信息
- classloader的兩種載入方式:1)pre-loading預先載入,載入基礎類 2)load-on-demand按需求載入
只有實例化一個類才會被classloader載入,僅僅申明并不會載入
-
java動態(tài)載入class的兩種方式:
1)implicit隱式,即利用實例化才載入的特性來動態(tài)載入class
2)explicit顯式方式,又分兩種方式:
1)java.lang.Class的forName()方法
2)java.lang.ClassLoader的loadClass()方法
-
static塊在什么時候執(zhí)行?
1)當調(diào)用forName(String)載入class時執(zhí)行,如果調(diào)用ClassLoader.loadClass并不會執(zhí)行.forName(String,false,ClassLoader)時也不會執(zhí)行.
2)如果載入Class時沒有執(zhí)行static塊則在第一次實例化時執(zhí)行.比如new ,Class.newInstance()操作
3)static塊僅執(zhí)行一次
Class類的實例.
>>Class類無法手工實例化,當載入任意類的時候自動創(chuàng)建一個該類對應的Class的實例,
>>某個類的所有實例內(nèi)部都有一個欄位記錄著該類對應的Class的實例的位置.,
>>每個java類對應的Class實例可以當作是類在內(nèi)存中的代理人.所以當要獲得類的信息(如有哪些類變量,有哪些方法)時,都可以讓類對應的Class的實例代勞.java的Reflection機制就大量的使用這種方法來實現(xiàn)
>>每個java類都是由某個classLoader(ClassLoader的實例)來載入的,因此Class類別的實例中都會有欄位記錄他的ClassLoader的實例,如果該欄位為null,則表示該類別是由bootstrap loader載入的(也稱root laoder),bootstrap loader不是java所寫成,所以沒有實例.
原生方法:forName0()等方法,native修飾符
-
自定義ClassLoader:
如實例化一個URLClassLoader. URLClassLoader ucl = new URLClassLoader(new URL[]{new URL("file:/e:/bin/")}),URLClassLoader優(yōu)先找當前目錄,再在url中找.class加載.URL中別忘在最后加"/"表示目錄
-
各個java類由哪些classLoader加載?
1)java類可以通過實例.getClass.getClassLoader()得知
2)接口由AppClassLoader(System ClassLoader,可以由ClassLoader.getSystemClassLoader()獲得實例)載入
3)ClassLoader類由bootstrap loader載入
-
ClassLoader hierachy:
jvm建立->初始化動作->產(chǎn)生第一個ClassLoader,即bootstrap loader->bootstrap loader在sum.misc.Launcher類里面的ExtClassLoader,并設定其Parent為null->bootstrap loader載入sun.misc.Launcher$AppClassLoader,并設定其parent為ExtClassLoader(但是AppClassLoader也是由bootstrap loader所載入的)->AppClassLoader載入各個xx.class,xx.class也有可能被ExtclassLoader或者bootstrap loader載入.
>>自定義的ClassLoader的.getParent()是AppClassLoader.parent和他的加載器并沒有關系
>>ExtClassLoader和AppClassLoader都是URLClassLoader的子類.AppClassLoader的URL是由系統(tǒng)參數(shù)java.class.path取出的字符串決定,而java.class.path由 運行java.exe時 的-cp或-classpath或CLASSPATH環(huán)境變量決定
>>ExtClassLoader查找的url是系統(tǒng)變量java.ext.dirs,java.ext.dirs默認為jdk\jre\lib\ext
>>Bootstrap loader的查找url是sun.boot.class.path
>>在程序運行后調(diào)用System.setProperty()來改變系統(tǒng)變量并不能改變以上加載的路徑,因為classloader讀取在System.setProperty之前.sun.boot.class.path是在程序中寫死的,完全不能修改
委派模型
當classloader有類需要載入時先讓其parent搜尋其搜尋路徑幫忙載入,如果parent找不到,在由自己搜尋自己的搜尋路徑載入,ClassLoader hierachy本來就有這種性質(zhì)
NoClassDefFoundError和ClassNotFoundException
NoClassDefFoundError:當java源文件已編譯成.class文件,但是ClassLoader在運行期間在其搜尋路徑load某個類時,沒有找到.class文件則報這個錯
ClassNotFoundException:試圖通過一個String變量來創(chuàng)建一個Class類時不成功則拋出這個異常