JVM類加載機制和內存模型


一.JVM類加載機制

  首先需要了解一下類加載器(ClassLoader)

    ClassLoader是Java的一個核心組件,它主要作用是從系統外部獲得Class二進制數據流,然后將數據流裝載到系統,交給JVM進行連接,初始化等操作,所有的Class都是有ClassLoader進行加載的。

    點開ClassLoader類,如下圖所示:

    

  類加載器種類

    啟動類加載器(BootStrapClassLoader):它用來加載 Java 的核心類,如java.xxx。

    擴展類加載器(ExtensionsClassLoader):它負責加載JRE的擴展目錄,如javax.xxx。

    應用類加載器(AppClassLoader):它一般用來加載程序所在目錄下的類。

    自定義類加載器:通過繼承ClassLoader類實現自定義類加載器。

  雙親委派機制:

    虛擬機是根據類的全限定名來加載類的,那么有個問題,如果同時存在兩個或多個全限定名完全一致的情況下,該如何選擇加載哪個類?如何判斷該類是否被加載過了?這都是雙親委派機制能做的。

    下圖是雙親委派機制的實現(這是ClassLoader中的loadClass方法),很明顯,parent也是一個類加載器。

    

    雙親委派機制原理:

      1.一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,直到啟動類加載器

      2.啟動類加載器檢查能不能加載(使用findClass()方法),能就加載(結束);否則,拋出異常,通知子加載器進行加載。

    雙親委派機制的優點是:

      1.安全,可避免用戶自己編寫的類動態替換Java的核心類,如java.lang.String
      2.避免全限定命名的類重復加載(使用了findLoadClass()判斷當前類是否已加載)

  附:Java跨平台實現的原理:Java源碼首先被編譯成字節碼(不同平台編譯后的字節碼是一樣的,因此在不同平台上運行時不需要重新編譯),再由不同平台的JVM進行解析,將字節碼轉換成具體平台上的機器指令。

  類加載流程:

    加載:通過ClassLoader加載class文件字節碼,生成Class對象

    連接:檢查加載的class文件的正確性和安全性;為類變量分配存儲空間並設置類變量初始值;JVM將常量池內的符號引用轉換為直接引用

    初始化:執行類變量賦值和靜態代碼塊

  類加載的方式:

    隱式加載:通過new關鍵字來創建實例對象。

    顯式加載:

      通過Class.forName()來加載類,它得到的是已經初始化完成的class

      通過類加載器的loadClass()方法來加載類,它得到的class還沒有完成連接過程

二.JVM內存模型

   

  所有線程共享的內存數據區:方法區,堆。而虛擬機棧,本地方法棧和程序計數器都是線程私有的。

     1、存放於棧中的:

      每個線程包含一個棧區,棧中只保存基礎數據類型的對象和自定義對象的引用(如變量的名字)。

      每個棧中的數據(基礎數據類型和對象引用)都是私有的,其他棧不能訪問。

      方法的形式參數,方法調用完后從棧空間回收。

      引用對象的地址,引用完后,棧空間地址立即被回收,堆空間等待GC。

     2、存放於堆中的:

       存儲的全部是對象,每個對象包含一個與之對應的class信息

      Jvm只有一個堆區(heap)被所有線程共享,堆區中不存放基本類型和對象引用,只存放對象本身

     3、存放於方法區中的:

      存放線程所執行的字節碼指令

      跟堆一樣.被所有線程共享.方法區包含:static變量

  注意:Class實例在jdk1.6及之前是存放在方法區中, 在jdk1.7及之后存放在堆中

     常量池在jdk1.6及之前是存放在方法區中,在jdk1.7存放在堆中,在jdk1.8存放在元空間中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM