java url路径包含中文_谈谈 Java 类加载机制
概述
類加載器主要分為兩類,一類是 JDK 默認提供的,一類是用戶自定義的。 JDK 默認提供三種類加載器:
Bootstrap ClassLoader啟動類加載器:每次執(zhí)行java命令時都會使用該加載器為虛擬機加載核心類。該加載器是由native code實現(xiàn),而不是 Java 代碼,加載類的路徑為<JAVA_HOME>/jre/lib。特別的<JAVA_HOME>/jre/lib/rt.jar中包含了sun.misc.Launcher類, 而sun.misc.Launcher$ExtClassLoader和sun.misc.Launcher$AppClassLoader都是sun.misc.Launcher的內部類,所以拓展類加載器和系統(tǒng)類加載器都是由啟動類加載器加載的。Extension ClassLoader, 拓展類加載器:用于加載拓展庫中的類。拓展庫路徑為<JAVA_HOME>/jre/lib/ext/。實現(xiàn)類為sun.misc.Launcher$ExtClassLoaderSystemClassLoader系統(tǒng)類加載器:用于加載 CLASSPATH 中的類。實現(xiàn)類為sun.misc.Launcher$AppClassLoader
歡迎學Java和大數(shù)據(jù)的朋友們加入java架構交流: 855835163
群內提供免費的架構資料還有:Java工程化、高性能及分布式、高性能、深入淺出。高架構。性能調優(yōu)、Spring,MyBatis,Netty源碼分析和大數(shù)據(jù)等多個知識點高級進階干貨的免費直播講解 可以進來一起學習交流哦
用戶自定義的類加載器
Custom ClassLoader, 一般都是java.lang.ClassLoder的子類
正統(tǒng)的類加載機制是基于雙親委派的,也就是當調用類加載器加載類時,首先將加載任務委派給雙親,若雙親無法加載成功時,自己才進行類加載。
在實例化一個新的類加載器時,我們可以為其指定一個 parent,即雙親,若未顯式指定,則 System ClassLoader 就作為默認雙親。
具體的說,類加載任務是由 ClassLoader 的 loadClass() 方法來執(zhí)行的,他會按照以下順序加載類:
- 通過
findLoadedClass()看該類是否已經被加載。該方法為 native code 實現(xiàn),若已加載則返回。 - 若未加載則委派給雙親,
parent.loadClass(),若成功則返回。 - 若未成功,則調用
findClass()方法加載類。java.lang.ClassLoader中該方法只是簡單的拋出一個ClassNotFoundException所以,自定義的 ClassLoader 都需要 OverridefindClass()方法。
類加載API
java.lang.ClassLoader
ClassLoader是一個抽象類。- 待加載的類必須用
The Java? Language Specification定義的全類名,全類名的定義請查閱 The Form of a Binary。 - 給定一個全類名,類加載器應該去定位該類所在的位置。通用的策略是將全類名轉換為類文件路徑,然后通過類文件路徑在文件系統(tǒng)中定位。
- 每一個加載到內存的類都由一個 Class 對象來表示,每一個 Class 對象都有一個指向加載該類的類加載器的引用。但是數(shù)組的 Class 對象是由 Java 運行時環(huán)境創(chuàng)建的,通過
Class.getClassLoader()方法返回的是數(shù)組元素的類加載器,若數(shù)組元素是基本類型,則返回null,若類是由Bootstrap ClassLoader加載的話也是返回null。 publicclassMain {publicstaticvoidmain(String[] args) {// Object 類在 <java_home>/jre/lib/rt.jar 中,// 由 Bootstrap ClassLoader 加載,由于該類加載器是由 native code 編寫// 所以輸出為 nullObject[] objects = newObject[5];System.out.println();System.out.println(objects.getClass().getClassLoader());// ZipFileAttributes 類在 <java_home>/jre/lib/ext/zipfs.jar 中,// 由 Extension ClassLoader 加載,// 輸出為 sun.misc.Launcher$ExtClassLoader@4b67cf4dZipFileAttributes[] attributes = newZipFileAttributes[5];System.out.println();System.out.println(attributes.getClass().getClassLoader());// Main 類是自定義的類,// 默認由 System ClassLoader 加載,// 輸出為 sun.misc.Launcher$AppClassLoader@18b4aac2Main[] array = newMain[5];array[0] = newMain();System.out.println();System.out.println(array.getClass().getClassLoader());}} ClassLoader默認支持并行加載,但是其子類必須調用ClassLoader.registerAsParallelCapable()來啟用并行加載- 一般來說,JVM 從本地文件系統(tǒng)加載類的行為是與平臺有關的。
defineClass()方法可以將字節(jié)流轉換成一個Class對象。然后調用Class.newInstance()來創(chuàng)建類的實例
java.security.SecureClassLoader
增加了一層權限驗證,因為關注點不在安全,所以暫不討論。
java.net.URLClassLoader
該類加載器用來加載 URL 指定的 JAR 文件或目錄中的類和資源,以 / 結尾的 URL 認為是目錄,否則認為是 JAR 文件。
// 嘗試通過 URLClassLoader 來加載桌面下的 Test 類。public class Main {public static void main(String[] args) {try {URL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File("/home/chen/Desktop/");String repository = (new URL("file", null,classPath.getCanonicalPath() + File.separator)).toString();urls[0] = new URL(null, repository, streamHandler);ClassLoader loader = new URLClassLoader(urls);Class testClass = loader.loadClass("Test");// output: java.net.URLClassLoader@7f31245aSystem.out.println(testClass.getClassLoader());} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}}
Tomcat 8.5.15類加載機制
Tomcat 使用正統(tǒng)的類加載機制(雙親委派),但部分地方做了改動。
Bootstrap classLoader和Extension classLoader的作用不變。System classLoader正常情況下加載的是CLASSPATH下的類,但是 Tomcat 的啟動腳本并未使用該變量,而是從以下倉庫下加載類:
$CATALINA_HOME/bin/bootstrap.jar包含了 Tomcat 的啟動類。在該啟動類中創(chuàng)建了Common classLoader、Catalina classLoader、shared classLoader。因為$CATALINA_BASE/conf/catalina.properties中只對common.loader屬性做了定義,server.loader和shared.loader屬性為空,所以默認情況下,這三個 classLoader 都是CommonLoader。具體的代碼邏輯可以查閱org.apache.catalina.startup.Bootstrap類的initClassLoaders()方法和createClassLoader()方法。$CATALINA_BASE/bin/tomcat-juli.jar包含了 Tomcat 日志模塊所需要的實現(xiàn)類。$CATALINA_HOME/bin/commons-daemon.jar。
Common classLoader是位于 Tomcat 應用服務器頂層的公用類加載器。由其加載的類可以由 Tomcat 自身類和所有應用程序使用。掃描路徑由$CATALINA_BASE/conf/catalina.properties文件中的common.loader屬性定義。默認是$CATALINA_HOME/lib。catalina classLoader用于加載服務器內部可見類,這些類應用程序不能訪問。shared classLoader用于加載應用程序共享類,這些類服務器不會依賴。Webapp classLoader。每個應用程序都會有一個獨一無二的webapp classloader,他用來加載本應用程序/WEB-INF/classes和/WEB-INF/lib下的類。
特別的:Webapp classLoader 的默認行為會與正常的雙親委派模式不同:
- 從
Bootstrap classloader加載。 - 若沒有,從
/WEB-INF/classes加載。 - 若沒有,從
/WEB-INF/lib/*.jar加載。 - 若沒有,則依次從
System、Common、shared加載(該步驟使用雙親委派)。
當然了,我們也可以通過配置來使 Webapp classLoader 嚴格按照雙親委派模式加載類:
- 通過在工程的
META-INF/context.xml(和WEB-INF/classes在同一目錄下) 配置文件中添加<Loader delegate="true"/> - 因為
Webapp classLoader的實現(xiàn)類是org.apache.catalina.loader.WebappLoader,他有一個屬性叫delegate, 用來控制類加載器的加載行為,默認為false,我們可以使用set方法,將其設為true來啟用嚴格雙親委派加載模式。
嚴格雙親委派模式加載步驟:
- 從
Bootstrap classloader加載。 - 若沒有,則依次從
System、Common、shared加載。 - 若沒有,從
/WEB-INF/classes加載。 - 若沒有,從
/WEB-INF/lib/*.jar加載。
歡迎學Java和大數(shù)據(jù)的朋友們加入java架構交流: 855835163
群內提供免費的架構資料還有:Java工程化、高性能及分布式、高性能、深入淺出。高架構。性能調優(yōu)、Spring,MyBatis,Netty源碼分析和大數(shù)據(jù)等多個知識點高級進階干貨的免費直播講解 可以進來一起學習交流哦
總結
以上是生活随笔為你收集整理的java url路径包含中文_谈谈 Java 类加载机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最近播出的调音师好看吗
- 下一篇: 《看恽家牡丹花戏赠李二十》第一句是什么