天天看點

分析Java的類加載器與ClassLoader(二):classpath與查找類位元組碼的順序,分析ExtClassLoader與AppClassLoader的源碼

先回顧一下classpath

classpath的作用:

        classpath的作用是指定查找類的路徑:當使用java指令執行一個類(類中的main方法)時,會從classpath中進行查找這個類。 

指定classpath的方式一: 

        設定環境變量CLASSPATH,多個路徑之間使用英文的分号隔開,也可以指定為jar包路徑。 

         示例:CLASSPATH=c:/myclasses/;c/mylib/aa.jar;c:/mylib/bb.jar;. 

         注意:在Windows中不區分大小寫,是以指定的環境變量名為classpath或是ClassPath都一樣。 

指定classpath的方式二: 

         在執行java指令時通過-classpath參數指定。 

         示例:java -classpath c:/myclasses/;c:/mylib/aa.jar cn.itcast.MainApp 

         注意:這樣就會隻是用這個參數指定的classpath,找不到類就報錯,不會使用CLASSPATH環境變量! 

指定classpath時各個路徑的順序: 

        試驗的結論是 按classpath中指定的順序,先從前面的路徑中查找,如果找不到,在從下一個路徑中查找,直到找到類位元組碼或是報NoClassDefFoundError。 

另外一種指定類路徑方式: 

        把類位元組碼檔案打成jar包,并放到JRE的lib/ext/目錄下,這樣在執行時就可以直接找到這個類而不需要指定classpath了。 

類加載器與classpath

從上一個文章中我們知道了類加載器預設使用三個: 

1,Bootstrap ClassLoader,啟動類加載器,負責加載核心Class(即所有java.*開頭的Class)。 

2,Extension ClassLoader,擴充類加載器,負責加載存放在JRE的lib/ext/目錄下的jar包中的Class。 

3,Application ClassLoader,應用程式類加載器,負責加載應用程式自身的類(CLASSPATH目錄中的Class)。 

分析ExtClassLoader

        Extension ClassLoader負責加載擴充類路徑中的類(預設為JRE的lib/ext/目錄) ,也就是說隻要把jar包放到這個目錄中,就可以直接使用裡面的類位元組碼而不需要指定classpath !注意這要求一定要在這個目錄中放jar包,直接把.class檔案放到這個目錄中不行。分析一下源碼(sun.misc.Launcher$ExtClassLoader類):

         Application ClassLoader負責加載CLASSPATH目錄中的Class ,也就是說classpath是給這個類加載器用的。分析一下源碼(sun.misc.Launcher$AppClassLoader類): 

當AppClassLoader遇上ExtClassLoader

        如果JRE的lib/ext/目錄下的jar包有某個類,我們指定的classpath中也有這個類,會怎麼樣呢?想想類加載查找類位元組碼的政策!結論是會執行lib/ext/xx.jar中的類! 因為類加載器使用委托模式進行類加載,并且ExtClassLoader是AppClassLoader的上級,是以AppClassLoader會先讓ExtClassLoader加載。如果父的類加載器沒有找到,自己才會加載。 

結論: 

1,把jar包放到擴充類路徑中就可以直接使用其中的類(預設是JRE的lib/ext/目錄)

2,classpath是給AppClassLoader配置的。 

3,如果擴充類路徑中有某個類,classpath中也有這個類,則會使用擴充類路徑中的類。 

http://www.tuicool.com/articles/bQFnqmi