您好,登錄后才能下訂單哦!
很多人說JVM是不是真的要學?面試官都會問JVM的問題嗎?很重要嗎?
的確很重要。
隨著互聯網的發展,高并發高可用、快速響應成為軟件的必須,而JVM與這些有著密切關聯。
我們在盡情享受Java虛擬機帶來好處的同時,還應該去了解和思考“這些技術特性是如何實現的”,去了解最底層的原理。只有熟悉JVM,你才能在遇到OutOfMemory等異常時,不會束手無策,不會一臉懵逼的上網找解決辦法,最后就算改了幾個啟動參數解決了問題,也還是云里霧里。
其實,“為什么學Java虛擬機”這個問題,就和“為什么要學習數據結構和算法”是一個道理:工欲善其事,必先利其器。可以說,Java虛擬機就是每一位Java工程師進階加薪的利器,你想往上升,你想深入技術,不想一直停留在簡單開發,或者你在做Java性能分析、調優工作時,那么,Java虛擬機絕對是一把助力的利劍。
1.內存模型以及分區,需要詳細到每個區放什么。
JVM 分為堆區和棧區,還有方法區,初始化的對象放在堆里面,引用放在棧里面,class類信息常量池(static常量和static變量)等放在方法區
new:
方法區:主要是存儲類信息,常量池(static常量和static變量),編譯后的代碼(字節碼)等數據
堆:初始化的對象,成員變量 (那種非static的變量),所有的對象實例和數組都要在堆上分配
棧:棧的結構是棧幀組成的,調用一個方法就壓入一幀,幀上面存儲局部變量表,操作數棧,方法出口等信息,局部變量表存放的是8大基礎類型加上一個應用類型,所以還是一個指向地址的指針
本地方法棧:主要為Native方法服務
程序計數器:記錄當前線程執行的行號
2.堆里面的分區:Eden,survival (from+ to),老年代,各自的特點。
堆里面分為新生代和老生代(java8取消了永久代,采用了Metaspace),新生代包含Eden+Survivor區,survivor區里面分為from和to區,內存回收時,如果用的是復制算法,從from復制到to,當經過一次或者多次GC之后,存活下來的對象會被移動到老年區,當JVM內存不夠用的時候,會觸發Full GC,清理JVM老年區
當新生區滿了之后會觸發YGC,先把存活的對象放到其中一個Survice 區,然后進行垃圾清理。因為如果僅僅清理需要刪除的對象,這樣會導致內存碎 片,因此一般會把Eden 進行完全的清理,然后整理內存。那么下次GC 的時候, 就會使用下一個Survive,這樣循環使用。如果有特別大的對象,新生代放不下, 就會使用老年代的擔保,直接放到老年代里面。因為JVM 認為,一般大對象的存 活時間一般比較久遠。
3.對象創建方法,對象的內存分配,對象的訪問定位。
new 一個對象
4.GC的兩種判定方法:
引用計數法:指的是如果某個地方引用了這個對象就+1,如果失效了就-1,當為0就會回收但是JVM沒有用這種方式,因為無法判定相互循環引用(A引用B,B引用A)的情況
引用鏈法: 通過一種GC ROOT的對象(方法區中靜態變量引用的對象等-static變量)來判斷,如果有一條鏈能夠到達GC ROOT就說明,不能到達GC ROOT就說明可以回收
5.SafePoint是什么
比如GC的時候必須要等到Java線程都進入到safepoint的時候VMThread才能開始執行GC,
循環的末尾 (防止大循環的時候一直不進入safepoint,而其他線程在等待它進入safepoint)
方法返回前
調用方法的call之后
拋出異常的位置
6.GC的三種收集方法:標記清除、標記整理、復制算法的原理與特點,分別用在什么地方,如果讓你優化收集方法,有什么思路?
先標記,標記完畢之后再清除,效率不高,會產生碎片
復制算法:分為8:1的Eden區和survivor區,就是上面談到的YGC
標記整理:標記完畢之后,讓所有存活的對象向一端移動
7.GC收集器有哪些?CMS收集器與G1收集器的特點。
并行收集器:串行收集器使用一個單獨的線程進行收集,GC時服務有停頓時間
串行收集器:次要回收中使用多線程來執行
CMS收集器是基于“標記—清除”算法實現的,經過多次標記才會被清除
G1從整體來看是基于“標記—整理”算法實現的收集器,從局部(兩個Region之間)上來看是基于“復制”算法實現的
8.Minor GC與Full GC分別在什么時候發生?
新生代內存不夠用時候發生MGC也叫YGC,JVM內存不夠的時候發生FGC
9.幾種常用的內存調試工具:jmap、jstack、jconsole、jhat
jstack 可以看當前棧的情況,jmap 查看內存,jhat 進行 dump 堆的信息
mat(eclipse 的也要了解一下)
10.類加載的幾個過程
加載、驗證、準備、解析、初始化。然后是使用和卸載了
通過全限定名來加載生成 class 對象到內存中,然后進行驗證這個 class 文件,包括文
件格式校驗、元數據驗證,字節碼校驗等。準備是對這個對象分配內存。解析是將符
號引用轉化為直接引用(指針引用),初始化就是開始執行構造器的代碼
11.JVM內存分哪幾個區,每個區的作用是什么?
java 虛擬機主要分為以下一個區:
方法區:
12.如和判斷一個對象是否存活?(或者GC對象的判定方法)
判斷一個對象是否存活有兩種方法:
虛擬機棧中引用的對象
方法區類靜態屬性引用的對象
方法區常量池引用的對象
本地方法棧 JNI 引用的對象
雖然這些算法可以判定一個對象是否能被回收,但是當滿足上述條件時,一個對象比不一
定會被回收。當一個對象不可達 GC Root 時,這個對象并
不會立馬被回收,而是出于一個死緩的階段,若要被真正的回收需要經歷兩次標記
如果對象在可達性分析中沒有與 GC Root 的引用鏈,那么此時就會被第一次標記并且進行
一次篩選,篩選的條件是是否有必要執行 finalize()方法。當對象沒有覆蓋 finalize()方法
或者已被虛擬機調用過,那么就認為是沒必要的。
如果該對象有必要執行 finalize()方法,那么這個對象將會放在一個稱為 F-Queue 的對隊
列中,虛擬機會觸發一個 Finalize()線程去執行,此線程是低優先級的,并且虛擬機不會承
諾一直等待它運行完,這是因為如果 finalize()執行緩慢或者發生了死鎖,那么就會造成 F-
Queue 隊列一直等待,造成了內存回收系統的崩潰。GC 對處于 F-Queue 中的對象進行
第二次被標記,這時,該對象將被移除”即將回收”集合,等待回收。
13.簡述java垃圾回收機制?
在 java 中,程序員是不需要顯示的去釋放一個對象的內存的,而是由虛擬機自行執行。在
JVM 中,有一個垃圾回收線程,它是低優先級的,在正常情況下是不會執行的,只有在虛
擬機空閑或者當前堆內存不足時,才會觸發執行,掃面那些沒有被任何引用的對象,并將
它們添加到要回收的集合中,進行回收。
14.java中垃圾收集的方法有哪些?
15.java內存模型
java 內存模型(JMM)是線程間通信的控制機制.JMM 定義了主內存和線程之間抽象關系。
線程之間的共享變量存儲在主內存(main memory)中,每個線程都有一個私有的本地
內存(local memory),本地內存中存儲了該線程以讀/寫共享變量的副本。本地內存是
JMM 的一個抽象概念,并不真實存在。它涵蓋了緩存,寫緩沖區,寄存器以及其他的硬
件和編譯器優化。Java 內存模型的抽象示意圖如下:
從上圖來看,線程 A 與線程 B 之間如要通信的話,必須要經歷下面 2 個步驟:
16.java類加載過程?
java 類加載需要經歷一下 7 個過程:
加載
加載時類加載的第一個過程,在這個階段,將完成一下三件事情:
解析
該階段主要完成符號引用到直接引用的轉換動作。解析動作并不一定在初始化動作完成之
前,也有可能在初始化之后。
初始化
初始化時類加載的最后一步,前面的類加載過程,除了在加載階段用戶應用程序可以通過
自定義類加載器參與之外,其余動作完全由虛擬機主導和控制。到了初始化階段,才真正
開始執行類中定義的 Java 程序代碼。
17. 簡述java類加載機制?
虛擬機把描述類的數據從 Class 文件加載到內存,并對數據進行校驗,解析和初始化,最
終形成可以被虛擬機直接使用的 java 類型。
18. 類加載器雙親委派模型機制?
當一個類收到了類加載請求時,不會自己先去加載這個類,而是將其委派給父類,由父類
去加載,如果此時父類不能加載,反饋給子類,由子類去完成類的加載。
19.什么是類加載器,類加載器有哪些?
實現通過類的權限定名獲取該類的二進制字節流的代碼塊叫做類加載器。
主要有一下四種類加載器:
20.簡述java內存分配與回收策率以及Minor GC和Major GC
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。