雖然是老碼農一枚,可是基本上沒有寫過文章(主要仍是我的太懶了),最近開始決定把本身以前學的知識作一下總結,順便也進行一下回顧。這裏總結和回顧的是Jvm系列,是基於周志明寫的《深刻理解java虛擬機》進行的總結,本章是對jvm內存模型的整理。html
知識點:
jvm內存模型
依照書中所寫,對這塊內容畫一個圖,咱們依照這幅圖來說。從圖中咱們能夠看出主要分爲6個部分,程序計數器、虛擬機棧、本地方法棧、方法區、堆、直接內存,一些區域爲線程獨佔,一些區域爲線程共享。java
1. 這塊區域比較簡單~~~~,是一塊較小的內存空間,存放線程當前執行的字節碼指令(包括異常處理、跳轉、分支等),由於操做系統的運做模式是一個cpu由多線程共享,當cpu處理了部分當前線程的邏輯以後可能會將時間片分給另外一個線程進行邏輯處理,處理完另外一個線程的邏輯以後又怎麼回來呢?這時候程序計數器就起到了相當重要的做用。他會記錄線程上一個處理的點,再回來的時候找到該點並繼續處理。
2. 若是執行的是native方法,該計數器爲空。
3. 惟一一個規範中沒有規定任何oom的區域。
4. 線程私有。面試
1. 在執行方法的時候,會產生一個棧幀,其中就存放了該方法的局部變量、出口地址、操做數棧等信息。這裏重點講一個局部變量表,裏面存放了編譯期可知的全部數據類型,當一個方法運行的時候,其局部變量表就已經固定了,不會再變。
2. 此區域包含兩種異常:線程請求的棧深度大於虛擬機容許的深度時會報stackoverflow異常;若是虛擬機棧動態擴展時申請不到足夠內容則會報oom異常。
3. 在總內存必定的狀況下,若是一個線程所須要的棧比較大,那麼總體可分配線程就會變少,此時若是必定要再分配線程,能夠經過參數減小其餘區域的內存空間,或者修改代碼下降線程所需棧大小來解決。
4. 線程私有。
大致模型以下:
編程
1. 機制和虛擬機棧差很少,顧名思義,區別在調native方法時候纔會用到。同樣是stackoverflow和oom異常。
2. 線程私有。segmentfault
1. 這個區域比較重要,咱們平時分配對象實例的時候(new xxx())都是在和這個區域打交道(固然也不是絕對,你們能夠想一想哪一種狀況下不在堆上分配對象(#^.^#)),平時遇到的oom也都是這個區域出現居多,包括咱們所說的jvm垃圾回收、內存管理,大多數都是指該內存區域,通常來講,該區域也是全部區域中最大的區域。後面針對該區域,咱們會再說一下對象是如何在內存中佈局的。基於虛擬機規範,物理上內容能夠不用連續,可是邏輯內存須要連續,因此整體是可擴展的(經過-Xmx、-Xms)。後面會再具體介紹下。
2. 咱們日常所說的新生代、老年代都是在這個區域中,大概內存模型以下(默認值),後面介紹gc的時候會具體介紹:
3. 這個不用多說,異常就是oom。
4. 線程共享。對於併發編程中是如何解決該區域的線程共享問題,後面的系列文章會講到。(感興趣請持續關注)。多線程
1. 該區域在jdk1.8以前稱爲永久代,1.8以後稱爲元數據空間。該區域存放類的元數據、常量、靜態變量信息等。jdk1.8以前可經過(-XX:MaxPermSize)來設置大小,1.8以後用(-XX:MaxMetaspaceSize)這個設置元數據空間大小,後面試過會再更新。
2. 若是分配的時候空間不夠報oom異常。
3. 元數據空間具體參數設置參照http://www.javashuo.com/article/p-bwuxmtkr-cs.html
4. 線程共享。併發
1. 又稱爲堆外內存,不屬於jvm管理,經過(-XX:MaxDirectMemorySize)設置大小,默認是和堆內存同樣。堆外內存在不少目前主流的技術中用到,好比netty就是使用堆外內存來減小數據拷貝,從而提高性能。
2. 雖然不受jvm內存大小限制,可是受操做系統內存大小限制,不夠一樣會報oom。
3. 線程共享。jvm
以上主要介紹了jvm內存中6個運行時數據區,總體仍是比較簡單清晰的,後一篇會介紹對象的內存佈局以及逃逸分析技術,敬請期待。
參考資料:周志明《深刻理解Java虛擬機》佈局