Java的JVM學習、類加載器(一)

JVM是什麼?

JVM(Java Virtual Machine,Java虛擬機):java程序首先需要通過javac來編譯,生成.class文件,然後通過java.exe(windows上)去運行,實際上java.exe是會去裝載jvm.dll不同平臺下是不一樣的(linux下的libjvm.dll)。

jvm是jre的一部分,他是一個虛構出來的計算機,擁有自己完善的硬件架構,如處理器、堆棧、寄存器等。
更多關於JVM的概念介紹:百度百科

JVM結構

JVM內部大概分爲三個部分,分別是類裝載器(ClassLoader)子系統,運行時數據區(Runtime Data Area)、和執行引擎(ExecutionEngine):
JVM結構圖

類裝載器(ClassLoader)子系統

其主要作用是將class文件進行裝載,然後可以得到該類的類類型,然後類類型的實例化就是新建每個新的對象,但是他們的信息都是與模板一樣:如下圖
類加載器
類加載器出去用戶自定義有三種:

    1. BootStrap:啓動類加載器,C++編寫的,java的根基 rt.jar (Runtime)
    1. Extension:擴展類加載器 Java 用於java擴展的 jar
    1. AppClassLoader:應用程序類加載器,也叫系統類加載器,加載當前應用的classpath的所有類
      參考代碼,查看結果:
public class MyObjectDemo01 {
    public static void main(String[] args) {
        Object object = new Object();
        // System.out.println(object.getClass().getClassLoader().getParent().getParent());
        // System.out.println(object.getClass().getClassLoader().getParent());
        // 這是屬於java自己的類,是使用BootStrap加載器進行加載的,所以上面兩個寫出時會報空指針異常找不到其父類  null
        System.out.println(object.getClass().getClassLoader());

        MyObjectDemo01 myObjectDemo01 = new MyObjectDemo01();

        //  null
        System.out.println(myObjectDemo01.getClass().getClassLoader().getParent().getParent());
        // sun.misc.Launcher$ExtClassLoader@3a71f4dd
        System.out.println(myObjectDemo01.getClass().getClassLoader().getParent());
        // sun.misc.Launcher$AppClassLoader@18b4aac2 自己定義的類,走的是AppClassLoader加載器
        // sun.misc.Launcher JVM的入口程序
        System.out.println(myObjectDemo01.getClass().getClassLoader());
    }
}
null
null
sun.misc.Launcher$ExtClassLoader@3a71f4dd
sun.misc.Launcher$AppClassLoader@18b4aac2

首先是自己的類,會通過AppClassLoader進行類加載,但不是第一次就是通過該加載器加載,後面會講爲什麼。而BootStrap是使用c寫的,所以打印的時候會是null。

雙親委派

首先參考一段代碼:

public class String {
    public static void main(String[] args) {
        /**
         * 錯誤: 在類 java.lang.String 中找不到 main 方法, 請將 main 方法定義爲:
         *    public static void main(String[] args)
         * 否則 JavaFX 應用程序類必須擴展javafx.application.Application
         */
        System.out.println("我是自己定義的類...");

    }
}

我這裏的包名:package java.lang;這樣情況如果java不存在一個類似於安全校驗的東西,那麼下一個使用String類的對象就不知道改使用哪個,所以引出雙親委派沙箱安全

當一個類接收到了類加載器請求,該發出請求的類加載器不會自己先去嘗試加載這個類,而是將這個請求委派給父類去完成,所以,所有的加載請求都會傳送到啓動類加載器(BootStrap)進行加載,如果父類反饋自己無法完成此次加載(就是在其加載路徑下沒有找到對應的class文件),子類加載器纔會去嘗試自己加載。
這樣做的好處就是,不管是使用什麼類加載器去加載String,都會先通過父加載器(Bootstrap)進行加載,這樣能保證最後加載到的String對象是同一個對象.
沙箱安全:JVM將不同的代碼放在不同的域中,從而控制權限

謝謝大家閱讀!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章