為了保證兼容性,JDK9沒有從根本上改變三層類加載器的架構和雙親委派模型,但為了模塊化系統的順利運行,仍然發生了一些值得被注意的變動
。
一、變動1
由于引入了模塊化概念,所以不同的類加載器回去加載屬于不同模塊的類
啟動類加載器
平臺類加載器
應用類加載器
二、變動二
擴展機制被移除,但是擴展類加載器由于向后兼容性的原因被保留,然后被重命名為平臺類加載器Platform ClassLoader
,可以通過ClassLoader的新增方法getPlatformClassLoader來獲取。
原因: JDK9是基于模塊化進行構建的,它將原來的rt.jar和tools.jar拆分成了很多的JMOD文件,文件中的Java類庫已經天然地滿足了可擴展的需求
,所以擴展機制已經沒有繼續存在的價值了。
public class ClassLoaderTest {public static void main(String[] args) {System.out.println(ClassLoaderTest.class.getClassLoader());System.out.println(ClassLoaderTest.class.getClassLoader().getParent());System.out.println(ClassLoaderTest.class.getClassLoader().getParent().getParent());}
}
三、變動三
平臺類加載器和應用程序類加載器都不再繼承于java.net.URLClassLoader,而是繼承于jdk.internal.loader.BuiltinClassLoader
,并且連啟動類加載器都是。
四、變動四
類加載器有了名稱屬性,該名稱可以在構造方法中進行指定,通過getName方法來獲取。應用類加載器的默認名稱是app,平臺類加載器的默認名稱是platform。
五、變動五
啟動類加載器現在是由JVM內部和Java類庫共同協作實現的類加載器,但為了與之前代碼進行兼容,在嘗試獲取啟動類加載器時仍然會返回null
,而不會得到對應的BootClassLoader實例。
六、變動六
類加載的委派關系發生了變動。
- 對比
- 在JDK9之前的版本中,當擴展及應用程序類加載器收到類加載請求,會委派給父加載器加載,只有當父加載器反饋自己無法完成這個加載請求時,才會由子類加載器嘗試進行加載。
在JDK9之后的版本中,當平臺及應用程序類加載器收到類加載請求,在委派給父加載器加載前,要先判斷該類是否能夠歸屬到某一個系統模塊中,如果可以找到這樣的歸屬關系,就要優先委派給負責那個模塊的加載器完成加載
。
七、測試代碼
public class DemoApplication {public static void main(String[] args) {System.out.println(DemoApplication.class.getClassLoader());System.out.println(DemoApplication.class.getClassLoader().getParent());System.out.println(DemoApplication.class.getClassLoader().getParent().getParent());// 獲取系統類加載器System.out.println(ClassLoader.getSystemClassLoader());// 獲取平臺類加載器System.out.println(ClassLoader.getPlatformClassLoader());// 獲取類的加載器的名稱System.out.println(DemoApplication.class.getClassLoader().getName());System.out.println(DemoApplication.class.getClassLoader().getParent().getName());ModuleLayer layer = ModuleLayer.boot();Set<Module> allModules = layer.modules();//打印所有已加載模塊及其對應的類加載器for (Module module : allModules) {ClassLoader classLoader = module.getClassLoader();ModuleDescriptor descriptor = module.getDescriptor();System.out.println("Module: " + descriptor.name() +", Class Loader: " + classLoader);}}
}