JVM體系結(jié)構(gòu)

JVM體系結(jié)構(gòu)

ClassLoader

將Class加載到內(nèi)存

結(jié)構(gòu)

  • BootstrapClassLoader:加載Java核心庫(kù)(JAVA_HOME/jre/lib),唯一一個(gè)使用本地代碼編寫的加載器
  • ExtensionClassLoader:加載擴(kuò)展庫(kù)(JAVA_HOME/jre/lib/ext和系統(tǒng)參數(shù)java.ext.dirs指定的目錄),它的父加載器是null(因?yàn)锽ootstrapClassLoader是使用C++實(shí)現(xiàn)的,沒有對(duì)應(yīng)的java類)
  • SystemClassLoader:加載應(yīng)用類的類文件(Classpath下的類文件)
  • UserDefineClassLoader:加載用戶定義的類文件,可以從網(wǎng)絡(luò)或者數(shù)據(jù)庫(kù)中加載類文件,實(shí)現(xiàn)類文件加密解密,動(dòng)態(tài)地創(chuàng)建符合應(yīng)用特殊需要的定制化類等
ClassLoader.png

雙親委派機(jī)制

加載器在接收到加載類的請(qǐng)求時(shí),首先檢查自己的緩存,確認(rèn)類是否已被加載,如果沒有加載,則將請(qǐng)求委托給父加載器,依次遞歸,如果父加載器完成加載,則成功返回,否則才自己去加載

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
  // 檢查類是否已被加載
  Class c = findLoadedClass(name);
  if (c == null) {                
    try {
      if (parent != null) {
        // 委托父類去加載
        c = parent.loadClass(name, false);
      } else {
        // parent為空,代表父類是BootstrapClassLoader
        c = findBootstrapClassOrNull(name);
      }
    } catch (ClassNotFoundException e) {
      // ClassNotFoundException thrown if class not found
      // from the non-null parent class loader
    }

    if (c == null) {
      // 父類沒有加載,才自己去加載
      c = findClass(name);
    }
  }

  if (resolve) {
    resolveClass(c);
  }
  return c;
}

意義:避免重復(fù)加載,避免安全因素(如果不采用這種機(jī)制,那么系統(tǒng)核心的類就可以被隨意替換)

** 不同類加載器加載的類不是相同類型:在Java中,一個(gè)類的全名(包名+類名)作為其標(biāo)識(shí),但在JVM中,一個(gè)類用其全名+類加載器作為唯一標(biāo)識(shí),不同類加載器加載的類置于不同的命名空間中**

線程上下文類加載器

雙親委派模式不能解決全部的加載問題。
Java提供了很多服務(wù)提供者接口(Service Provider Interface,SPI),常見的有JDBC、JNDI、JAXP等。這些SPI接口由Java核心庫(kù)提供(通過BootstrapClassLoader加載),而它們的實(shí)現(xiàn)由第三方庫(kù)提供(通過SystemClassLoader加載)。但很多時(shí)候,SPI接口需要加載具體的實(shí)現(xiàn)類,如 JAXP 中的javax.xml.parsers.DocumentBuilderFactory類中的newInstance()方法用來生成一個(gè)新的DocumentBuilderFactory的實(shí)例。這里的實(shí)例的真正的類是繼承自 javax.xml.parsers.DocumentBuilderFactory,由 SPI 的實(shí)現(xiàn)所提供的。如在 Apache Xerces 中,實(shí)現(xiàn)的類是 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl。問題是BootstrapClassLoader是無(wú)法找到 SPI 的實(shí)現(xiàn)類的,因?yàn)樗患虞d Java 的核心庫(kù)。它也不能代理給SystemClassLoader,因?yàn)樗荢ystemClassLoader的祖先類。

而線程上下文類加載器就是解決這個(gè)問題,如果不做任何的設(shè)置,Java的線程的上下文類加載器默認(rèn)就是SystemClassLoader。在SPI接口的代碼中使用線程上下文類加載器,就可以成功的加載到SPI實(shí)現(xiàn)的類。

使用線程上下文加載器,要注意保證多個(gè)需要通信的線程間的類加載器應(yīng)該是同一個(gè),防止因?yàn)椴煌念惣虞d器導(dǎo)致類型轉(zhuǎn)換異常(ClassCastException)。

運(yùn)行時(shí)區(qū)域

運(yùn)行時(shí)區(qū)域

Method Area

已加載的類信息(類結(jié)構(gòu)、方法、字段、靜態(tài)變量)
常量池:字符串、整形(-127-128)
一般稱為Permanent Generation

線程執(zhí)行

每個(gè)線程都有一個(gè)PC Register、JVM Stack、Native Method Stack
PC Register:下一條要執(zhí)行的指令的地址
JVM Stack:包含一系列的Stack Frame,每次方法調(diào)用都會(huì)創(chuàng)建一個(gè)Frame并壓棧,每個(gè)棧幀都對(duì)應(yīng)一個(gè)被調(diào)用的方法(使用遞歸容易讓棧溢出,通過-Xss設(shè)置棧大?。?。同時(shí)那些方法內(nèi)的局部變量,也是在這里創(chuàng)建


Stack Frame

Heap

Heap

存放實(shí)例對(duì)象和數(shù)組
分成Young、Tenured、Permanent三個(gè)不同區(qū)域,其中Young又分成Eden和兩個(gè)相同大小的Survivor:From、To
為什么要分代:不同對(duì)象的生命周期是不一樣的,采用不同的收集算法,可以提高回收效率

例子

public class Test {
  public static void main(String[] args) {
    public Test2 t2 = new Test2(); 
    //JVM將Test2類信息加載到方法區(qū),new Test2()實(shí)例保存在堆區(qū),Test2引用保存在棧區(qū)
  }
}

參考

http://docs.oracle.com/javase/specs/jvms/se7/jvms7.pdf
http://blog.csdn.net/zhoudaxia/article/details/35897057
http://www.ibm.com/developerworks/cn/java/j-lo-classloader/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,034評(píng)論 25 709
  • 一、JVM體系結(jié)構(gòu) JVM體系結(jié)構(gòu)分為4部分 類加載器、執(zhí)行引擎、內(nèi)存區(qū)、本地方法調(diào)用 1. 類...
    onlinemf閱讀 500評(píng)論 0 1
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,798評(píng)論 11 349
  • 人長(zhǎng)長(zhǎng)以為自己長(zhǎng)情 以為自己戀舊 呵呵 只是現(xiàn)在過得不好罷了
    勵(lì)志名句閱讀 321評(píng)論 0 0
  • 經(jīng)常會(huì)接到一些電話,360手機(jī)軟件會(huì)提示此號(hào)碼為詐騙電話。于是我在想,為什么會(huì)有這么多的詐騙電話?是騙子太多,還是...
    汀然Amily閱讀 1,539評(píng)論 0 1

友情鏈接更多精彩內(nèi)容