再談JVM中類加載

前言

因爲本人蔘加面試,可是JVM這塊回答的十分很差,問了面試官,面試官說我基礎不行!我真的不行,因此看過的不必定能理解,感受以前就是糊弄任務,而後此次等實訓結束,啥都幹完了,我就記錄下,深刻了解下面試中不會的題。java

類加載過程

一、加載:這個很簡單,程序運行以前jvm會把編譯完成的.class二進制文件加載到內存,供程序使用,用到的就是類加載器classLoader ,這裏也能夠看出java程序的運行並非直接依 靠底層的操做系統,而是基於jvm虛擬機。若是沒有類加載器,java文件就只是磁盤中的一個普通文件。程序員

二、鏈接:鏈接是很重要的一步,過程比較複雜,分爲三步 驗證 》準備 》解析   面試

  驗證:確保類加載的正確性。通常狀況由javac編譯的class文件是不會有問題的,可是可能有人的class文件是本身經過其餘方式編譯出來的,這就頗有可能不符合jvm的編 譯規則,這一步就是要過濾掉這部分不合法文件 數據結構

  準備:爲類的靜態變量分配內存,將其初始化爲默認值 。咱們都知道靜態變量是能夠不用咱們手動賦值的,它天然會有一個初始值 好比int 類型的初始值就是0 ;boolean類型初始值爲false,引用類型的初始值爲null 。 這裏注意,只是爲靜態變量分配內存,此時是沒有對象實例的 jvm

  解析:把類中的符號引用轉化爲直接引用。解釋一下符號引用和直接引用。好比在方法A中使用方法B,A(){B();},這裏的B()就是符號引用,初學java時咱們都是知道這是java的引用,覺得B指向B方法的內存地址,可是這是不完整的,這裏的B只是一個符號引用,它對於方法的調用沒有太多的實際意義,能夠這麼認爲,他就是給程序員看的一個標誌,讓程序員知道,這個方法能夠這麼調用,可是B方法實際調用時是經過一個指針指向B方法的內存地址,這個指針纔是真正負責方法調用,他就是直接引用。操作系統

三、初始化:爲類的靜態變量賦予正確的初始值,上述的準備階段爲靜態變量賦予的是虛擬機默認的初始值,此處賦予的纔是程序編寫者爲變量分配的真正的初始值
線程

建立對象時的內存分配狀況

類加載究竟是什麼呢?其實類加載不過就是居民虛擬機爲類分配了幾塊內存空間,說的具體一點,就是jvm虛擬機將類的.class文件加載到內存,並將它放到運行時數據區的方法區內,而後在堆區建立一個java.lang.Class對象,用來封裝類在方法區內的數據結構指針

這裏可能不少人不知道什麼是運行時方法區。咱們簡單瞭解一下jvm虛擬機的內存管理對象

Java虛擬機在執行Java程序的過程當中會把它所管理的內存劃分爲若干個不一樣的數據區域。這些區域都有各自的用途,以及建立和銷燬的時間,有的區域隨着虛擬機進程的啓動而存在,有些區域則依賴用戶線程的啓動和結束而創建和銷燬。java虛擬機所管理的內存將會包括如下幾個運行時數據區域
blog

不少區域的做用你們可能都不知道,這裏也很少作解釋,咱們只須要知道 其中的兩個

方法區:用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據

堆區:存放對象實例,幾乎全部的對象實例都在這裏分配內存

也就是說,類被加載後,方法區會被分出一塊內存,存儲這個類的全部信息,可是這個內存塊存儲的依然是.class文件,並不能被咱們使用,咱們還須要一個能被直接使用的對象,此時堆區就開始發揮做用。類的信息被存儲在方法區後,jvm虛擬機又會在堆區建立一個java.lang.Class對象,這個對象就好像方法區對應類的一個鏡子,把方法區存儲的類的結構所有反射過來,而後封裝起來,成爲了一個Class類的對象(此處運用到反射知識)。這個Class對象與對應的類是一對一服務,由於他有類的結構信息,因此他天然能夠構造出一個類的對象。咱們平時使用的對象就是由這個Class類的對象生成。到此,類的加載已經完成,可是此時依舊沒有咱們須要使用的對象產生(這裏比較繞,說的比較囉嗦)

總結

  • 類的加載的最終產品是位於堆區中的Class 對象
  • Class對象封裝了類在方法區內的數據結構,而且向Java程序員提供了訪問方法區內的數據結構的接口
相關文章
相關標籤/搜索