由於疫情的原因,所以目前一直在家遠程辦公,所以很多時間在刷面試題,發現2019大廠的面試雖然種類很多,但是總結了一下發現主要是這幾點:演算法和數據結構、 JVM、集合、多線程、資料庫這幾點在面試的時候比較多。今天總結了幾個JVM比較問的多的問題和答案希望可以幫到大家。 1、首先就是JVM垃圾回收機制和 ...
由於疫情的原因,所以目前一直在家遠程辦公,所以很多時間在刷面試題,發現2019大廠的面試雖然種類很多,但是總結了一下發現主要是這幾點:演算法和數據結構、
JVM、集合、多線程、資料庫這幾點在面試的時候比較多。今天總結了幾個JVM比較問的多的問題和答案希望可以幫到大家。
1、首先就是JVM垃圾回收機制和演算法
這個應該是問得最多的幾個問題之一了,大家都知道java是由sun公司發明的(後來由於經營不善被甲骨文收購了),Sun 公司只定義了垃圾回收機制規則而不局限於其實現演算法,因此不同廠商生產的虛擬機採用的演算法也有所不同。
GC(Garbage Collector)在回收對象前首先必鬚髮現那些無用的對象,如何去發現定位這些無用的對象?一共有兩種搜索演算法:引用計數器演算法、根搜索演算法,由於引用計數器演算法已經被廢棄,所已這裡主要說明根搜索演算法:
根搜索演算法:
根搜索演算法是通過一些“GC Roots”對象作為起點,從這些節點開始往下搜索,搜索通過的路徑成為引用鏈(Reference Chain),當一個對象沒有被 GC Roots 的引用鏈連接的時候,說明這個對象是不可用的。
GC Roots 對象包括:
a) 虛擬機棧(棧幀中的本地變數表)中的引用的對象。 b) 方法區域中的類靜態屬性引用的對象。 c) 方法區域中常量引用的對象。 d) 本地方法棧中 JNI(Native 方法)的引用的對象。 通過上面的演算法搜索到無用對象之後,就是回收過程,回收演算法分為以下4種:1)標記—清除演算法(Mark-Sweep)(DVM 使用的演算法)
標記—清除演算法包括兩個階段:“標記”和“清除”。在標記階段,確定所有要回收的對象,並做標記。清除階段緊隨標記階段,將標記階段確定不可用的對象清除。標記—清除演算法是基礎的收集演算法,標記和清除階段的效率不高,而且清除後回產生大量的不連續空間,這樣當程式需要分配大記憶體對象時,可能無法找到足夠的連續空間。
2)複製演算法(Copying)
複製演算法是把記憶體分成大小相等的兩塊,每次使用其中一塊,當垃圾回收的時候,把存活的對象複製到另一塊上,然後把這塊記憶體整個清理掉。複製演算法實現簡單,運行效率高,但是由於每次只能使用其中的一半,造成記憶體的利用率不高。現在的 JVM 用複製方法收集新生代,由於新生代中大部分對象(98%)都是朝生夕死的,所以兩塊記憶體的比例不是 1:1(大概是 8:1)。
3)標記—整理演算法(Mark-Compact)
標記—整理演算法和標記—清除演算法一樣,但是標記—整理演算法不是把存活對象複製到另一塊記憶體,而是把存活對象往記憶體的一端移動,然後直接回收邊界以外的記憶體。標記—整理演算法提高了記憶體的利用率,並且它適合在收集對象存活時間較長的老年代。
4)分代收集(Generational Collection)
分代收集是根據對象的存活時間把記憶體分為新生代和老年代,根據各個代對象的存活特點,每個代採用不同的垃圾回收演算法。新生代採用複製演算法,老年代採用標記—整理演算法。垃圾演算法的實現涉及大量的程式細節,而且不同的虛擬機平臺實現的方法也各不相同。
2、談談 JVM 的記憶體結構和記憶體分配
1)Java 記憶體模型:Java 虛擬機將其管轄的記憶體大致分三個邏輯部分:方法區(Method Area)、Java 棧和 Java 堆。
1、方法區是靜態分配的,編譯器將變數綁定在某個存儲位置上,而且這些綁定不會在運行時改變。常數池,源代碼中的命名常量、String 常量和 static 變數保存在方法區。
2、Java Stack 是一個邏輯概念,特點是後進先出。一個棧的空間可能是連續的,也可能是不連續的。最典型的 Stack 應用是方法的調用,Java 虛擬機每調用一次方法就創建一個方法幀(frame),退出該方法則對應的 方法幀被彈出(pop)。棧中存儲的數據也是運行時確定的。 3、Java 堆分配(heap allocation)意味著以隨意的順序,在運行時進行存儲空間分配和收回的記憶體管理模型。堆中存儲的數據常常是大小、數量和生命期在編譯時無法確定的。Java 對象的記憶體總是在 heap 中分配。