jvm面試我只看這篇

前言

這是一篇看了能說的出來的jvm面試;我的能力有限,文中描述不免有錯誤,請指正;html

一 JVM面試

1.1 簡述Java內存模型(重點)

jvm會將運行程序所管理的空間分爲若干部分,每一個部分都起到相當重要的部分;jdk1.8java運行時數據區以下:java

程序計數器:當前線程執行字節碼的行號指示器;字節碼解析器經過改變計數器的值,來選取下一條須要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能;面試

Java 虛擬機棧: java方法執行的內存模型,每一個方法被執行的時候都會建立幀棧用於存儲局部變量表、操做數棧、動態連接、方法出口等信息;算法

本地方法棧: 執行java的native方法服務,每一個方法被執行的時候都會建立幀棧用於存儲局部變量表、操做數棧、動態連接、方法出口等信息;數組

Java 堆: 儲存對象的實例和數組;安全

方法區: 非堆,儲存類的結構信息;例如運行時常量池的字段和方法數據,構造函數和普通方法的字節碼內容等;併發

科普運行時經常使用池:運行時經常使用池是class文件中每個類或者接口的常量池表的運行表現形式,包括若干種常量,如字段和方法的引用;在類加載至虛擬機的時候就會建立運行時常量池;

科普幀棧:幀棧用於儲存數據和部分過程結果的數據,同時也會處理動態連接,方法返回值和分派;幀棧隨着方法的建立而建立,隨着方法的銷燬而銷燬;幀棧中維護着本地變量表,操做數棧,和指向當前方法所屬類的運行常量池的引用;oracle

注意:jdk1.8已經使用元空間替代了jdk1.7方法區中的永久代,元空間存在於native內存中,其大小根據本地內存而定,沒有限制;詳細看官網地址jvm

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html#sthref66socket

1.2 簡述類的加載過程(重點)

類的加載過程分爲 加載,連接,初始化,使用,和卸載5個階段,其中鏈接階段又分爲驗證 準備和解析階段;

  1. 加載階段:主要是得到類的二進制字節流在內存中生產Class對象;
  2. 鏈接階段:驗證Class的安全性,符合虛擬機規範;準備類的內存分配和初始化變量;解析常量池的符號引用(將符號引用轉換爲直接引用);
  3. 初始化階段:對靜態變量和靜態代碼賦初值;
  4. 使用階段;
  5. 卸載階段;

1.3 哪些地方會發生OOM?

內存溢出:申請了8個字節的空間,可是你在這個空間寫入9或以上字節的數據,出現內存溢出;

在java內存模型中只有程序計數器不會發生OOM(out of memory),其他地區都會發生OOM;

1.4 什麼是雙親委派模型?

當一個類收到了類加載請求時,本身不會先去加載這個類,而是將其委派給父類去加載,若是父類不能加載,反饋給子類,由子類去完成類的加載;

這邊有可能會問,你都知道哪些類加載器

  1. 啓動類加載器:主要加載%JAVA_HOME%\lib 目錄下的類庫文件或者 -Xbootclasspath 所指定的類庫文件(加載核心類)
  2. 擴展類加載器:主要加載%JAVA_HOME%\lib\ext目錄下的類庫文件或者java.ext.dirs系統變量所指定的類庫文件(加載擴展庫)
  3. 程序應用類加載器:主要加載用戶類路徑(classpath)所指定的類庫。
  4. 用戶自定義類加載器:加載用戶自定義的類庫。

如何打破雙親委派模型

雙親委派模型都依靠loadClass(),重寫loaderClass()便可;

1.5 新生代中區分Eden和Survivor的做用是什麼

新生代分爲 3 個分區:Eden(伊甸園)、Survivor一、Survivor2;其中Survivor一、 Survivor2 合起來成爲Survivor(倖存區); 若是沒有Survivor,Eden區每進行一次Minor GC,存活的對象都會被送到老年代。老年代將很快被填滿,老年代每發生一次Full GC 的速度比 Minor GC慢10倍;

Survivor 的做用就是減小老年代 Full GC 的次數,至關於緩衝帶;

Eden和Survivor的比例分配8:1;

1.6簡述分代垃圾回收器工做流程

  1. 衆多的對象都分配在Eden;
  2. 一個survivor空間接收來自Eden存活的對象;
  3. 2 個survivor 空間的對象會相互複製,無論survivor 空間的對象如何複製,總有一個survivor 空間是空的用於接收來自Eden存活的對象;
  4. 當survivor 空間不足時,對象就會複製到老年代;

官網:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/generations.html#sthref16

1.7 簡述內存分配與回收策略(重點)

  • 大多數狀況下對象都優先直接分配在Eden ,當Eden 空間不足時會發生Minor GC, 每通過一次Minor GC,年齡+1,若年齡超過15,則被進入到老年態。當老年代空間不足時就會發生 Full GC;
  • 長期存活對象將進入老年代
  • 若是是大對象(須要大量連續內存空間的對象)直接進入老年代 ;
會出現的小問題就是:Minor GC和Full GC觸發條件,答默認狀況下發生15次Minor GC以後就會觸發一次Full GC

1.8 GC是什麼? 爲何要有 GC?

GC 是垃圾收集(GabageCollection);Java 提供的 GC 功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的,而不須要人爲手動釋放內存;主要調用的是 System.gc() 和 Runtime.getRuntime().gc();

1.9 簡述CMS收集器

CMS(Concurrent Mark Sweep)收集器基於標記—清除算法實現的收集器,是一種以獲取最短回收停頓時間爲目標的收集器。主要優勢是併發收集,低停頓,在cpu多核的狀況下性能較好。在啓動 JVM 的參數加上

「-XX:+UseConcMarkSweepGC」來指定使用 CMS 垃圾回收器;其使用在老年代 能夠配合新生代的Serial和ParNew收集器一塊兒使用;因爲 CMS 使用 標記—清除算法 GC時會產生大量碎片,有可能提早觸發Full GC;若是在老年代充滿以前沒法回收不可達對象,或者沒有足夠的空間知足分配就會致使Concurrent Mode Failure(併發模式故障);

官網:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html

2.0 簡述G1收集器

G1(Garbage-First)從總體來看是基於標記—整理算法實現的收集器,可以實現併發並行,對cpu利用率較高,減小停頓時間。目標是取代jdk1.5發佈的CMS收集器。G1收集器收集範圍是老年代和新生代,不須要結合其餘收集器使用,G1收集器可預測垃圾回收的停頓時間,對空間進行整合;因爲G1是基於複製算法實現,當沒有足夠的空間(region)分配存活的對象就會致使Allocation (Evacuation) Failure(分配失敗)

官網:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc.html#garbage_first_garbage_collection

2.1 jvm調優時如何選擇垃圾回收器(重點)

  • 當應用的數據集較小時,約100M時或者 單線程應用,沒有嚴格的停頓要求選擇serial 收集器; 參數選項:-XX:+UseSerialGC;
  • 若是對應用的性能要求高或者沒有停頓要求,能夠接受1秒或者更久的停頓選擇parallel收集器; 參數選項:XX:+UseParallelGC;
  • 若是對響應時間有很高的要求相比於吞吐量,追求更小的停頓時間可使用CMS或者G1; 參數選項:-XX:+UseConcMarkSweepGC 或者 XX:+UseG1GC

官網:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html#sthref27

2.2 簡述GC中Stop the world(重點)

Java中Stop-The-World機制簡稱STW,是在執行垃圾收集算法時,Java應用程序的其餘全部線程都被掛起。Stop-The-World對系統性能存在影響,所以垃圾回收的一個原則是儘可能減小「Stop-The-World」的時間;

2.3 垃圾回收算法(重點)

標記-清除法:標記出沒有用的對象,以後一個一個回收掉

  • 缺點:標記和清除兩個過程效率不高,產生內存碎片致使須要分配較大對象時沒法找到足夠的連續內存而須要觸發一次GC操做;
  • 優勢:實現簡單;

複製算法: 按照容量劃分二個大小相等的內存區域,當一塊用完的時候將活着的對象複製到另外一塊上,而後再把已使用的內存空間一次清理掉

  • 缺點:將內存縮小爲原來的一半;
  • 優勢:按順序分配內存,實現簡單、運行高效,不用考慮內存碎片。

標記-整理法:標記出沒有用的對象,讓全部存活的對象都向一端移動,而後直接清除掉端邊界之外的對象

  • 優勢:解決了標記- 清除算法致使的內存碎片問題。
  • 缺點:仍須要進行局部對象移動,必定程度上下降了效率。

分代回收:根據對象存活週期的不一樣將內存劃分爲幾塊,通常是新生代和老年代,新生代基本採用複製算法,老年代採用標記整理算法

2.4 你知道哪些垃圾收集器

2.5 你有遇到過java內存泄漏麼?(次重點)

內存泄漏:new申請了一塊內存,後來很長時間都再也不使用了(按理應該釋放),可是由於一直被某個或某些實例所持有致使 GC 不能回收;

經典案例

void test(){
Vector vector = new Vector();
for (int i = 1; i<100; i++)
{
Object object = new Object();
vector.add(object);
object = null;
}
//...對vector的操做
//...與vector無關的其餘操做
}

手動解決賦值null便可

void test(){
Vector vector = new Vector();
for (int i = 1; i<100; i++)
{
Object object = new Object();
vector.add(object);
object = null;
}
//...對vector的操做
vector = null;
//...與vector無關的其餘操做
}

還有各類流和socket的close方法未被調用也會發生內存泄漏問題;

2.6 對象何時會被GC

  • 引用計數器法:爲每一個對象建立一個引用計數,有對象引用時計數器 +1,引用被釋放時計數 -1,當計數器爲 0 時就能夠被回收。它有一個缺點不能解決循環引用(A->B,B->A)的問題,那麼 AB 將永遠不會被回收;
  • 可達性分析算法:從 GC Roots 開始向下搜索,搜索所走過的路徑稱爲引用鏈。當一個對象到 GC Roots 沒有任何引用鏈相連時,則證實此對象是能夠被回收的。

2.7 說下Java內存堆和棧區別(偶爾會問到)

  • 棧內存用來存儲基本類型的變量和對象的引用變量,堆內存用來存儲Java中的對象;
  • 棧內存線程私有,堆內存線程共享
  • 棧內存不足時,JVM會拋出java.lang.StackOverFlowError(通常發生在遞歸的時候);堆內存不足時,JVM會拋出java.lang.OutOfMemoryError
  • 棧的內存遠小於堆內存,-Xss選項設置棧的大小。-Xms選項能夠設置堆的開始大小;

2.8 強引用、軟引用、弱引用、虛引用以及他們之間和gc的關係

  • 強引用:new出的對象之類的引用, 只要強引用還在,gc時永遠不會被回收
  • 軟引用:有用但非必須的對象,內存溢出異常以前,回收
  • 弱引用:有用但非必須的對象,對象能生存到下一次垃圾收集發生以前。
  • 虛引用:對生存時間無影響,在垃圾回收時獲得通知。

2.9java對象建立

  • 使用new關鍵字建立對象; 會調用構造方法;
  • 使用Class類的newInstance方法(反射機制);會調用構造方法;
  • 使用Constructor類的newInstance方法(反射機制);會調用構造方法;
  • 使用Clone方法建立對象;不會調用構造方法;
  • 使用(反)序列化機制建立對象;不會調用構造方法;

3.0 若是對象的引用被置爲 null,垃圾收集器是否會當即回收對象?

不會,在下一個垃圾回收週期中回收對象。

3.1 jvm調優工具又哪些?各自的做用又是什麼(重點)

  • jps: 查看進程的參數信息;
  • jstat: 查看某個Java進程內的線程堆棧信息;
  • jinfo: 查看虛擬機參數;
  • jmap:查看堆內存使用情況,生成快照存儲(dump文件);
  • jhat: 分析jmap dump生成的快照文件;
  • jconsole: 基於JMX的可視化工具,監控 cpu, 內存,線程等使用狀況;
  • jvisualvm: JDK 自帶分析工具,功能齊全,如查看進行信息,快照轉存,監控cpu,線程,方法區,堆等;

3.2 你知道哪些JVM調優參數

  • -Xms128m JVM初始分配的堆內存
  • -Xmx512m JVM最大容許分配的堆內存,按需分配;
  • -XX:MetaspaceSize:分配給類元數據空間(以字節計)的初始大小;
  • -XX:MaxMetaspaceSize:分配給類元數據空間的最大值,超過此值就會觸發Full GC
  • -XX:NewRatio:新生代和老年代的佔比;
  • -XX:NewSize:新生代空間;
  • -XX:SurvivorRatio:伊甸園空間和倖存者空間的佔比;
  • -XX:MaxTenuringThreshold:對象進入老年代的年齡閾值;
  • XX:+PrintGC:打印 gc 信息;
  • -XX:+PrintGCDetails:打印 gc 詳細信息

若是你對文中的知識點不太理解 推薦閱讀周志明先生《深刻理解Java虛擬機:JVM高級特性與最佳實踐(第3版)》和做者給出的官網連接!!!!

求關注吖

相關文章
相關標籤/搜索