Java常見面試題(二)Java虛擬機(JVM)相關,長期更新中....

1、談談 JVM 內存區域的劃分?

  • 堆(Heap),它是 Java 內存管理的核心區域,是線程共享的一塊內存區域,用來放置 Java 對象實例,幾乎所有創建的 Java 對象實例都是被直接分配在堆上。堆被所有的線程共享,在虛擬機啓動時,我們指定的“Xmx”之類參數就是用來指定最大堆空間等指標。
  • 方法區(Method Area)。這也是所有線程共享的一塊內存區域,用於存儲所謂的元(Meta)數據,例如類結構信息,以及對應的運行時常量池、字段、方法代碼等。
  • Java 虛擬機棧(Java Virtual Machine Stack),早期也叫 Java 棧。每個線程在創建時都會創建一個虛擬機棧,其內部保存一個個的棧幀(Stack Frame),對應着一次次的 Java 方法調用。
  • 本地方法棧(Native Method Stack)。它和 Java 虛擬機棧是非常相似的,支持對本地方法的調用,也是每個線程都會創建一個 。PS:在 Oracle Hotspot JVM 中,本地方法棧和 Java 虛擬機棧是在同一塊兒區域,這完全取決於技術實現的決定,並未在規範中強制。
  • 程序計數器(PC,Program Counter Register)。在 JVM 規範中,每個線程都有它自己的程序計數器,並且任何時間一個線程都只有一個方法在執行,也就是所謂的當前方法。程序計數器會存儲當前線程正在執行的 Java 方法的 JVM 指令地址。
    在這裏插入圖片描述
    PS:運行時常量池(Run-Time Constant Pool),是方法區的一部分,常量池可以存放各種常量信息,不管是編譯期生成的各種字面量,還是需要在運行時決定的符號引用。

2、JVM 哪些區域可能發生 OutOfMemoryError(OOM)?

OutOfMemoryError (OOM)通俗點兒說,就是 JVM 內存不夠用了,沒有空閒內存,並且垃圾收集器也無法提供更多內存。在拋出 OutOfMemoryError 之前,通常垃圾收集器會被觸發,盡其所能去清理出空間。
除了程序計數器,其他區域都有可能會因爲可能的空間不足發生 OutOfMemoryError,簡單總結如下:

  • 堆(Heap)內存不足是最常見的 OOM 原因之一,拋出的錯誤信息是“java.lang.OutOfMemoryError:Java heap space”,原因可能千奇百怪,例如,可能存在內存泄漏問題;也很有可能就是堆的大小不合理,比如我們要處理比較大的數據量,但是沒有顯式指定 JVM 堆大小或者指定數值偏小;或者出現 JVM 處理引用不及時,導致堆積起來,內存無法釋放等。
  • Java 虛擬機棧和本地方法棧,
  • 而對於 Java 虛擬機棧本地方法棧,這裏要稍微複雜一點。如果我們寫一段程序不斷的進行遞歸調用,而且沒有退出條件,就會導致不斷地進行壓棧。類似這種情況,JVM 實際會拋出 StackOverFlowError,如果 JVM 試圖去擴展棧空間的的時候失敗,則會拋出 OutOfMemoryError。
  • 對於JDK1.8之前的版本,因爲永久代的大小是有限的,並且 JVM 對永久代垃圾回收(如,常量池回收、卸載不再需要的類型)非常不積極,所以當我們不斷添加新類型的時候,永久代出現 OutOfMemoryError 也非常多見,尤其是在運行時存在大量動態類型生成的場合,對應的異常信息,會標記出來和永久代相關:java.lang.OutOfMemoryError: PermGen space
  • JDK1.8引入元數據區,方法區內存已經不再那麼窘迫,所以相應的 OOM 有所改觀,出現 OOM,異常信息則變成了:java.lang.OutOfMemoryError: Metaspace

3、如何監控和診斷 JVM 堆內和堆外內存使用?

這兩篇文章總結的不錯:https://www.cnblogs.com/ysocean/p/11311667.html
https://www.cnblogs.com/ysocean/p/11415514.html

4、Java 常見的垃圾收集器有哪些?

參考:https://www.cnblogs.com/ysocean/p/11117365.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章