深刻淺出 Java 中 JVM 內存管理

來源:期待華麗轉身
cnblogs.com/developerxiaofeng/p/9214969.html

Java崗位面試,JVM是對程序員基本功考察,一般會問你對JVM瞭解嗎?html

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

1) JVM內存劃分:程序員

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

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

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

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

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

經過這幅圖瞭解一下服務器

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

詳細瞭解一下各個部分

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

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

程序計數器的做用:

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

程序計數器的特色

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

02)Java虛擬機棧

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

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

壓棧出棧過程:

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

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()方法就能在運行期間向常量池中添加字符串常量

06) 直接內存(堆外內存)

直接內存是除Java虛擬機以外的內存,但有可能被Java使用

操做直接內存:

在NIO中引入了一種基於通道和緩存的IO方式,他能夠調用本地方法的直接分配Java虛擬機以外的內存,而後經過一個存儲在堆中的DirectByteBuffer對象直接操做該內存,而無需將外部內存中數據複製到堆中再進行操做,從而提升數據操做的效率,直接內存的大小不受Java虛擬機,也會拋出OutOfMemoryError異常

直接內存和堆內存比較:

  • 直接內存申請空間耗費更高的性能
  • 直接內存讀取IO的性能優於普通的堆內存
  • 直接內存的做用鏈:本地IO-->直接內存-->本地IO
  • 堆內存的做用鏈:本地IO-->直接內存-->非直接內存-->直接內存--->本地IO
  • 服務器管理員在配置虛擬機參數時,會根據實際內存設置 -Xmx等參數信息,但常常忽略直接內存,使得各個內存區域總和大於物理內存,從而致使動態擴展時出現OutOFMemoryError

2)相似 -Xms  -Xmn這些參數的含義

堆內存分配

① : JVM初始分配的內存由-Xms指定,默認是物理內存的1/64

②:  JVM最大分配的內存由-Xmx指定,默認是物理內存的1/4

③: 默認空餘堆內存小於40%時,JVM就會增長堆直到-Xmx的最大限制;空餘堆內存大於70%時,JVM會減小堆直到-Xms的最小限制

④: 所以服務器通常設置-Xms  -Xmx相等以免在每次GC後調整堆大小. 對象的堆內存由成爲垃圾回收器的自動內存管理系統回收

非堆內存分配:

①:JVM使用-XX:PermSize 設置非堆內存的初始值,默認物理內存的1/64;

② :由XX:MaxPermSize設置設置最大非堆內存的大小

③: -Xmn2G :設置年輕代的大小爲2G

④ :-XX:SurvivorRatio ,設置年輕代中Eden區與Survivor區的比值

3)垃圾回收的算法有哪些?

① 引用計數法:原理是在此對象有個引用,即增長一個計數,刪除一個引用則減小一個計數.垃圾回收時,只收集計數爲0的對象.此算法的最致命的沒法處理循環引用的問題

②: 標記-清除 :此算法分兩個階段,第一階段從引用的根節點開始標記全部被引用的對象,第二階段遍歷整個堆,把未標記的對象清除,此算法須要暫停應用,同時產生內存碎片

③: 複製算法 此算法把內存劃分爲兩個相等的區域,每次只使用一個區域,垃圾回收時,遍歷當前使用的區域,把正在使用的對象複製到另外一個區域中每次算法每次只處理正在使用的對象,所以複製的成本比較小,同時複製過去之後還能進行相應的內存整理,不會出現"碎片問題",此算法的缺點也很明顯,須要兩倍的內存空間

④: 標記-整理:此算法結合了"標記-清除"和:複製算法的兩個的優勢,也是分兩個階段,第一個階段從根節點開始標記全部被引用對象,第二階段遍歷整個堆,清除未標記的對象而且把存活的對象"壓縮"到堆的其中一塊,按順序排放,,此算法避免"標記-清除"的碎片問題,同時也避免"複製"的空間問題

4)root搜索算法中,哪些能夠做爲root?

  • 被啓動類(bootstrap加載器)加載的類和建立的對象
  • JavaStack中引用的對象(棧內存中引用的對象)
  • 方法區中靜態引用

關注公衆號Java技術棧回覆"面試"獲取我整理的2020最全面試題及答案。

推薦去個人博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、後端、架構、阿里巴巴等大廠最新面試題

以爲不錯,別忘了點贊+轉發哦!

相關文章
相關標籤/搜索