JVM
    jvm是jre里頭一個(gè)動(dòng)態(tài)連接函數(shù)庫(kù),jdk里面的jre一般用于運(yùn)行java本身的程序,比如javac,等等.programfiles下面的jre用于運(yùn)行用戶編寫的java程序.
    JRE下的bin\client 或者 bin\server 的jvm.dll就是JVM了

    當(dāng)一臺(tái)機(jī)器上有多個(gè)jvm可選擇的時(shí)候,jvm的選擇步驟:
    1)當(dāng)前目錄有沒(méi)有jre目錄(不準(zhǔn)確),
    2)父目錄下的jre子目錄
    3)注冊(cè)表HEKY_LOCAL_MACHINE\SoftWare\Java\Java Runtime Environment\
    所以當(dāng)運(yùn)行的是jdk\bin\java.exe的時(shí)候,用的jre是bin的父目錄jdk下面的jre\
    運(yùn)行java.exe找到了jre后有一個(gè)驗(yàn)證程序,驗(yàn)證jre和java.exe的版本是否一致,如果不一致則會(huì)發(fā)生錯(cuò)誤


    java -verbose:class Main 顯示調(diào)用的詳細(xì)信息

    classloader的兩種載入方式:1)pre-loading預(yù)先載入,載入基礎(chǔ)類 2)load-on-demand按需求載入
    只有實(shí)例化一個(gè)類才會(huì)被classloader載入,僅僅申明并不會(huì)載入

    java動(dòng)態(tài)載入class的兩種方式:
    1)implicit隱式,即利用實(shí)例化才載入的特性來(lái)動(dòng)態(tài)載入class
    2)explicit顯式方式,又分兩種方式:
    1)java.lang.Class的forName()方法
    2)java.lang.ClassLoader的loadClass()方法

    static塊在什么時(shí)候執(zhí)行?
    1)當(dāng)調(diào)用forName(String)載入class時(shí)執(zhí)行,如果調(diào)用ClassLoader.loadClass并不會(huì)執(zhí)行.forName(String,false,ClassLoader)時(shí)也不會(huì)執(zhí)行.
    2)如果載入Class時(shí)沒(méi)有執(zhí)行static塊則在第一次實(shí)例化時(shí)執(zhí)行.比如new ,Class.newInstance()操作
    3)static塊僅執(zhí)行一次


    Class類的實(shí)例.
    >>Class類無(wú)法手工實(shí)例化,當(dāng)載入任意類的時(shí)候自動(dòng)創(chuàng)建一個(gè)該類對(duì)應(yīng)的Class的實(shí)例,
    >>某個(gè)類的所有實(shí)例內(nèi)部都有一個(gè)欄位記錄著該類對(duì)應(yīng)的Class的實(shí)例的位置.,
    >>每個(gè)java類對(duì)應(yīng)的Class實(shí)例可以當(dāng)作是類在內(nèi)存中的代理人.所以當(dāng)要獲得類的信息(如有哪些類變量,有哪些方法)時(shí),都可以讓類對(duì)應(yīng)的Class的實(shí)例代勞.java的Reflection機(jī)制就大量的使用這種方法來(lái)實(shí)現(xiàn)
    >>每個(gè)java類都是由某個(gè)classLoader(ClassLoader的實(shí)例)來(lái)載入的,因此Class類別的實(shí)例中都會(huì)有欄位記錄他的ClassLoader的實(shí)例,如果該欄位為null,則表示該類別是由bootstrap loader載入的(也稱root laoder),bootstrap loader不是java所寫成,所以沒(méi)有實(shí)例.

    原生方法:forName0()等方法,native修飾符


    自定義ClassLoader:
    如實(shí)例化一個(gè)URLClassLoader. URLClassLoader ucl = new URLClassLoader(new URL[]{new URL("file:/e:/bin/")}),URLClassLoader優(yōu)先找當(dāng)前目錄,再在url中找.class加載.URL中別忘在最后加"/"表示目錄

    各個(gè)java類由哪些classLoader加載?
    1)java類可以通過(guò)實(shí)例.getClass.getClassLoader()得知
    2)接口由AppClassLoader(System ClassLoader,可以由ClassLoader.getSystemClassLoader()獲得實(shí)例)載入
    3)ClassLoader類由bootstrap loader載入

    ClassLoader hierachy:
    jvm建立->初始化動(dòng)作->產(chǎn)生第一個(gè)ClassLoader,即bootstrap loader->bootstrap loader在sum.misc.Launcher類里面的ExtClassLoader,并設(shè)定其Parent為null->bootstrap loader載入sun.misc.Launcher$AppClassLoader,并設(shè)定其parent為ExtClassLoader(但是AppClassLoader也是由bootstrap loader所載入的)->AppClassLoader載入各個(gè)xx.class,xx.class也有可能被ExtclassLoader或者bootstrap loader載入.
    >>自定義的ClassLoader的.getParent()是AppClassLoader.parent和他的加載器并沒(méi)有關(guān)系
    >>ExtClassLoader和AppClassLoader都是URLClassLoader的子類.AppClassLoader的URL是由系統(tǒng)參數(shù)java.class.path取出的字符串決定,而java.class.path由 運(yùn)行java.exe時(shí) 的-cp或-classpath或CLASSPATH環(huán)境變量決定
    >>ExtClassLoader查找的url是系統(tǒng)變量java.ext.dirs,java.ext.dirs默認(rèn)為jdk\jre\lib\ext
    >>Bootstrap loader的查找url是sun.boot.class.path
    >>在程序運(yùn)行后調(diào)用System.setProperty()來(lái)改變系統(tǒng)變量并不能改變以上加載的路徑,因?yàn)閏lassloader讀取在System.setProperty之前.sun.boot.class.path是在程序中寫死的,完全不能修改

    委派模型
    當(dāng)classloader有類需要載入時(shí)先讓其parent搜尋其搜尋路徑幫忙載入,如果parent找不到,在由自己搜尋自己的搜尋路徑載入,ClassLoader hierachy本來(lái)就有這種性質(zhì)



    NoClassDefFoundError和ClassNotFoundException
    NoClassDefFoundError:當(dāng)java源文件已編譯成.class文件,但是ClassLoader在運(yùn)行期間在其搜尋路徑load某個(gè)類時(shí),沒(méi)有找到.class文件則報(bào)這個(gè)錯(cuò)
    ClassNotFoundException:試圖通過(guò)一個(gè)String變量來(lái)創(chuàng)建一個(gè)Class類時(shí)不成功則拋出這個(gè)異常