帶你玩玩類加載器

前言

看大部分博客講到類加載器時都會講一堆理論,稍顯枯燥,今天我就來帶你們玩點好玩的,手動加入拓展類,看看是否是真的是由擴展類加載器所加載?java

類加載器

  • Bootstrap ClassLoader(啓動類加載器)負責將%JAVA_HOME%/lib目錄中或-Xbootclasspath中參數指定的路徑中的,而且是虛擬機識別的(按名稱)類庫加載到JVM中
  • Extension ClassLoader(擴展類加載器)負責加載%JAVA_HOME%/lib/ext中的全部類庫
  • Application ClassLoader(應用程序加載器) 負責ClassPath中的類庫,就是用戶定義的類

擴展類加載器

package bingo;
public class Bingo {
    public static void main(String[] args) {
        System.out.println("關注J2彬彬");
    }
}
複製代碼

ext文件夾就是JDK存放擴展類的地方,將上面這段代碼編譯成class文件,放到下圖的的bingo文件夾下程序員

直接將bingo文件夾打成jar包,執行下圖命令,打成jar包後如上圖所示產生一個bingo.jar
在IDEA的類路徑下能夠看到我加入的jar包

下面是個簡單的案例後端

package com.bingo.classloader;

import bingo.Bingo;


public class ClassLoaderTest {

    public static void main(String[] args) {

        Object object = new Object();
        System.out.println("object加載器:"+object.getClass().getClassLoader());

        Bingo bingo = new Bingo();
        System.out.println("bingo加載器:"+bingo.getClass().getClassLoader());
        System.out.println("bingo加載器的父類:"+bingo.getClass().getClassLoader().getParent());

        ClassLoaderTest test = new ClassLoaderTest();
        System.out.println("test加載器:"+test.getClass().getClassLoader());
        System.out.println("test加載器的父類:"+test.getClass().getClassLoader().getParent());
        System.out.println("test加載器的父類的父類:"+test.getClass().getClassLoader().getParent().getParent());

    }
}
複製代碼

執行結果:微信

object加載器:null
bingo加載器:sun.misc.Launcher$ExtClassLoader@29453f44
bingo加載器的父類:null
test加載器:sun.misc.Launcher$AppClassLoader@18b4aac2
test加載器的父類:sun.misc.Launcher$ExtClassLoader@29453f44
test加載器的父類的父類:null
複製代碼

雙親委派模型

由執行結果能夠看出,Bingo類由ExtClassLoader加載,用戶自定義的類通常都是由AppClassLoader加載,而Object類在rt.jar下,由Bootstrap加載器加載,它是由C++實現的,因此打印結果爲null。getParent()獲得父類加載器,這裏就能夠看出雙親委派模型。學習

爲何要加載類須要委託雙親加載呢?spa

  • 每個類都只會被加載一次,避免了重複加載
  • 每個類都會被儘量的加載(從引導類加載器往下,每一個加載器均可能會根據優先次序嘗試加載它)
  • 有效避免了某些惡意類的加載(好比自定義了Java。lang.Object類,通常而言在雙親委派模型下會加載系統的Object類而不是自定義的Object類)

我是廣州的java程序員小彬,一直在致力於java後端的學習,下面是個人微信公衆號,裏面有更多有質量的文章,感謝你們!3d

相關文章
相關標籤/搜索