你們好,我是Java最全面試題庫
的提褲姐,今天這篇是面試系列的第十七篇,主要總結了JavaSE中JVM
相關面試題,這篇是JVM系列的第一篇,主要講解JVM的內存模型
,第二篇主要講解垃圾回收。在後續,會沿着第一篇開篇的知識線路一直總結下去,作到日更!若是我能作到百日百更,但願你也能夠跟着百日百刷,一百天養成一個好習慣。java
JVM分爲:面試
①方法區:主要是存儲類信息,常量池(static量和 static變量),編譯後的代碼(字節碼)等數據
②堆:初始化的對象,成員變量(那種非 static的變量),全部的對象實例和數組都要在堆上分配
③棧:棧的結構是棧幀組成的,調用一個方法就壓入一幀,幀上面存儲局部變量表,操做數棧,方法出口等信息,局部變量表存放的是8大基礎類型加上一個引用類型,因此仍是一個指向地址的指針
④本地方法棧:主要爲 Native方法服務
⑤程序計數器:記錄當前線程執行的行號算法
總結:初始化的對象放在堆裏面,引用放在棧裏面,class類信息常量池(static常量和 static變量)等放在方法區
JVM內存區域主要分爲:數組
. class文件
中的final常量值
和一些文本修飾的符號引用(類和接口的全限定名,字段的名稱和描述符,方法和名稱和描述符)。若是沒有Survivor,Eden區每進行一次Minor GC
,存活的對象就會被送到老年代。老年代很快被填滿,觸發Major GC
.老年代的內存空間遠大於新生代,進行一次Full GC
消耗的時間比Minor GC
長得多,因此須要分爲Eden和Survivor。
Survivor的存在乎義,就是減小被送到老年代的對象,進而減小Full GC的發生,Survivor的預篩選保證,只有經歷16
次Minor GC還能在新生代中存活的對象,纔會被送到老年代。
設置兩個Survivor區最大的好處就是解決了碎片化
,剛剛新建的對象在Eden中,經歷一次Minor GC,Eden中的存活對象就會被移動到第一塊survivor space S0,Eden被清空;等Eden區再滿了,就再觸發一次Minor GC,Eden和S0中的存活對象又會被複制送入第二塊survivor space S1(這個過程很是重要,由於這種複製算法保證了S1中來自S0和Eden兩部分的存活對象佔用連續的內存空間,避免了碎片化的發生)安全
一、大對象直接進入老年態
二、通過一次Minor GC,年齡+1,若年齡超過必定限制(15),則被晉升到老年態。即長期存活的對象進入老年態jvm
Perm Space中保存的是加載class文件
。spa
會引發OutOfMemory,出現異常能夠設置 -XX:PermSize
的大小。線程
JDK 1.8後,字符串常量不存放在永久代,而是在堆內存中,JDK1.8之後沒有永久代概念,而是用元空間替代,元空間不存在虛擬機中,二是使用本地內存。
JVM中類的裝載是由類加載器(ClassLoader)
和它的子類
來實現的,Java中的類加載器是一個重要的Java運行時系統組件,它負責在運行時查找和裝入類文件中的類。指針
因爲Java的跨平臺性,通過編譯的Java源程序並非一個可執行程序,而是一個或多個類文件。當Java程序須要使用某個類時,JVM會確保這個類已經被加載、鏈接(驗證、準備和解析)和初始化。code
類的加載是指把類的.class文件中的數據讀入到內存中,一般是建立一個字節數組讀入.class文件,而後產生與所加載類對應的Class對象。加載完成後,Class對象還不完整,因此此時的類還不可用。當類被加載後就進入鏈接階段,這一階段包括驗證
、準備
(爲靜態變量分配內存並設置默認的初始值)和解析
(將符號引用替換爲直接引用)三個步驟。最後JVM對類進行初始化,包括:
①若是類存在直接的父類而且這個類尚未被初始化,那麼就先初始化父類;
②若是類中存在初始化語句,就依次執行這些初始化語句。類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統加載器(System)和用戶自定義類加載器(java.lang.ClassLoader的子類)。從Java 2(JDK 1.2)開始,類加載過程採起了父親委託機制(PDM)。PDM更好的保證了Java平臺的安全性,在該機制中,JVM自帶的Bootstrap是根加載器,其餘的加載器都有且僅有一個父類加載器。類的加載首先請求父類加載器加載,父類加載器無能爲力時才由其子類加載器自行加載。JVM不會向Java程序提供對Bootstrap的引用。
內存區域 | 是否線程私有 | 是否會發生OOM |
---|---|---|
程序計數器 | 是 | 否 |
虛擬機棧 | 是 | 是 |
本地方法棧 | 是 | 是 |
方法區 | 否 | 是 |
直接內存 | 否 | 是 |
堆 | 否 | 是 |
JVM的堆是運行時數據區,全部類的實例和數組都是在堆上分配內存。它在JVM啓動的時候被建立。對象所佔的堆內存是由自動內存管理系統也就是垃圾收集器回收。堆內存是由存活和死亡的對象組成的。存活的對象是應用能夠訪問的,不會被垃圾回收。死亡的對象是應用不可訪問尚且尚未被垃圾收集器回收掉的對象。一直到垃圾收集器把這些對象回收掉以前,他們會一直佔據堆內存空間。