深入淺出 Java 中 JVM 內存管理你瞭解嗎?


小編最近回顧Java基礎,跟著小編一起學習吧!最近都會發表一些基礎,一起學習進步吧!

java崗位面試,JVM是對程序員基本功考察,通常會問你對JVM瞭解嗎?

可以分幾部分回答這個問題,首先JVM內存劃分 | JVM垃圾回收的含義 | 有哪些GC算法 以及年輕代和老年代各自特點等等。

1) JVM內存劃分:

① 方法區 (線程共享) 常量 靜態變量 JIT(即時編譯器)編譯後代碼也在方法區存放

② 堆內存(線程共享) 垃圾回收的主要場地

③ 程序計數器 當前線程執行的字節碼的位置指示器

④ Java虛擬機棧(棧內存) :保存局部變量,基本數據類型以及堆內存中對象的引用變量

⑤ 本地方法棧 (C棧):為JVM提供使用native方法的服務

通過這幅圖瞭解一下

深入淺出 Java 中 JVM 內存管理你瞭解嗎?


JDK 1.8同JDK 1.7 最大的區別是:元數據取代了永久代.元空間的本質和永久代類似,都是對JVM規範中的方法區的實現.其元空間和永久代之間的最大區別在於:元數據空間不在虛擬機中,而是在本地內存中

詳細瞭解一下各個部分

01)程序計數器(PC寄存器)

程序計數器的定義: 程序計數器是一塊較小的內存空間,是當前線程正在執行的哪一條字節碼指令的地址,若當前線程正在執行的是一個本地方法,那麼此時程序計數器為Undefined

程序計數器的作用:

  • 字節碼解釋器通過改變程序計數器來依次獲取指令,從而實現代碼的流程的控制
  • 在在多線程情況下,程序計數器記錄的是當前線程執行的執行的位置,從而當線程切換回來時,就知道上次線程執行到哪了

程序計數器的特點

  • 是一塊較小的內存空間
  • 線程私有,每個線程都有自己的程序計數器
  • 生命週期:隨著線程的創建而創建,隨著線程的銷燬而銷燬
  • 是一個唯一不會出現的OutOfMemoryError的內存區域


02)Java虛擬機棧

定義: 描述Java方法運行過程的內存模型

Java虛擬機棧會為每一個即將運行的Java方法創建一塊叫做"棧幀"的區域,用於存放該方法運行過程中的一些信息,如 局部變量表 /操作數棧 /動態鏈接 /方法出口信息 .............

深入淺出 Java 中 JVM 內存管理你瞭解嗎?


壓棧出棧過程:

當方法運行過程中需要創建局部變量時,就將局部變量的值存入棧幀的局部變量表中

Java虛擬機棧的棧頂是當前正在執行的活動棧,也就是當前正在執行的方法,PC寄存器也會指向這個地址,只有這個活動的棧幀的本地變量可以被操作數棧操作,當前這個棧幀中調用另一個方法,與之對應的額棧幀又會被創建,新創建的棧幀壓入棧頂,變成當前的活動棧幀,方法結束後,當前棧幀的返回值變成新的活動棧幀的中的操作數棧的一個操作數,如果沒有返回值,那麼新的活動棧幀中操作數棧的操作數沒有變化

由於Java虛擬機棧是線程對應的,數據不是共享的,因此不用關心數據一致性問題,也不會存在同步鎖的問題

特點

  • 局部變量表隨著棧幀的創建而創建,他的大小在編譯時確定,創建時只需分配事先規定的大小即可,在方法運行的過程中,局部變化表的大小不會發生變化
  • Java虛擬機棧會出現兩種異常:StackOverFlowError和OutOfMemoryError
  • StackOverFlowError若Java虛擬機棧的大小不允許動態擴展,那麼當前線程請求的棧的深度超過當前的Java虛擬機棧的最大深度是,就會拋出此異常
  • OutOFMemoryError,若允許動態擴展,那麼當前線程的請求的棧內存用完了,無法再動態擴展時,拋出此異常
  • Java虛擬機棧也是線程私有,隨著線程創建而創建,隨著線程的結束而銷燬


03)本地方法棧(C棧)

定義: 是為了JVM運行native方法準備的空間,由於很多native方法都是用C語言實現的,所以通常又叫C棧,它與Java虛擬機棧實現的功能類似,只不過本地方法棧描述本地方法運行過程的內存模型

棧幀變化過程:

本地方法被執行時,在本地方法棧也會創建一塊棧幀,用於存放該方法的局部變量表 /操作數棧 /動態鏈接 /方法出口等信息; 方法結束後,相應的棧幀也會出棧,並釋放內存空間.也會拋出StackOverFlowError和OutOfMemoryError異常

04) 堆

定義: 堆是用來對象的內存空間,幾乎所有的對象都存儲在堆中

特點:

  • 線程共享,整個Java虛擬機只有一個堆,所有線程都訪問同一個堆.
  • 在虛擬機啟動時創建
  • 是垃圾回收的主要場地
  • 進一步可分為:新生代(Eden區 From Survior To Surviror) 老年代
  • 不同的區域存放的不同生命週期的對象,這樣可以根據不同區域使用不同的垃圾回收算法,更具有針對性. 堆的大小也可以固定也可以擴展,對於主流的虛擬機,堆大小可擴展的,因此當線程請求分配的內存,但堆已滿,且內存已無法再擴展,就拋出OutOfMemoryError異常


05)方法區

定義: Java虛擬機規範中定義方法區是堆的一個邏輯部分,方法區存放以下信息 已被虛擬機加載的類信息 /常量 /靜態變量 /即時編譯後代碼

特點:

  • 線程共享.方法區是堆的一個邏輯部分,因此和堆一樣,都是線程共享,整個虛擬機中只有一個方法區
  • 永久代 方法區中的信息一般需要長期存在,而且它又是堆的邏輯分區,因此用堆的劃分方法,把方法區稱為"永久代"
  • 內存回收的效率低.方法區中的信息一般需要長期存在,回收一遍只有少量信息無效.主要回收的目標是: 對常量池的回收;對類型的卸載
  • Java虛擬機規範l對方法區的要求比較寬鬆,和堆一樣,允許固定大小.也允許動態擴展,還允許不實現垃圾回收


運行時常量池:

方法區中存放:類信息 常量 靜態變量 即時編譯器變編譯後代碼.常量就存放在運行時常量池中.當類被Java虛擬機加載後,.class文件中的常量就存在方法區的運行常量池,而且在運行期間,可以向常量池中添加新的常量,如String類的intern()方法就能在運行期間向常量池中添加字符串常量

你必須很努力,然後看起來才毫不費力!

關注我每天都有乾貨,看下期哦。


分享到:


相關文章: