Java VM中常常被問到,也須要掌握的VM兩個點,作一個小筆記java
絕大多的言語都有共同的點,你會抄你同窗的做業,那麼你可能不知道你同窗也會抄別人的做業,語言之間的底層構架也都差很少,Java底層的東西和其餘語言也有相似,好比C/C++、phython、JavaScript等等數組
之前的JDK,VM內存能夠分爲三個點研究學習: 棧stack、堆heap、方法區method areaoracle
方法區method area存在堆中,是被認爲比較特殊的存在,因此學習的時候會單拎知識點,有興趣的小夥伴也會去oracle官網看一下「元空間」,以及本地內存的改動運維
①表示方法執行的內存模型,每一個方法被調用都會建立一個棧幀(局部變量、操做數、方法出口等)jsp
②JVM爲每一個線程建立一個棧,用於存放該線程執行方法信息(實際參數、局部變量等)學習
③棧屬於線程私有,不能實現線程間的共享spa
④棧的存儲特性: 先進後出,後進先出線程
⑤棧是由系統自動分配,速度快,是一個連續的內存空間3d
方法執行,相關的調用都在棧中,每一個方法被調用都會建立一個棧幀對象
若是在藍色方法中再調用一個方法,會再生成一個新的棧幀,也同樣,最後依據「先進後出,後進先出」的順序,關閉執行完的方法,好比A方法中調用B方法,B方法調用C方法,那麼順序是A等B執行完,B等C執行完,C關閉=》B關閉=》A關閉
①用於存放建立好的對象和數組
②JVM只有一個堆,被全部線程共享
③堆是一個不連續的內存空間,分配靈活,速度慢
new完的對象存在堆中
以往的JVM中也只有一個方法區,被全部線程共享,屬於堆內的一部分,用於存儲類、常量相關的信息,用來存放程序中永遠不變或者惟一的內容,好比類信息[Class對象]、靜態變量、字符串常量等
JDK7字面量(interned strings)、類的靜態變量(class statics)轉移到堆中,可是永久在還存在於中,直到JDK8,永久代才徹底消失,轉而使用元空間
元空間是直接存在內存中,不在java虛擬機堆中,所以元空間依賴於內存大小,能夠自定義元空間大小,這裏面存儲的是類的元數據信息
類的元數據, 字符串池, 類的靜態變量將會從永久代移除, 放入堆或者本地內存. 其中官方建議JVM的實現中將類的元數據放入 native memory, 將字符串池和類的靜態變量放入堆中. 這樣加載多少類的元數據就不在由MaxPermSize控制, 而由系統的實際可用空間來控制
減小OOM是一種連帶緣由, 更深層的緣由仍是要合併HotSpot和JRockit, JRockit沒有永久代的東西, 運行狀態比較好, 也不須要開發運維人員設置大小來調控
"java.lang.OutOfMemoryError: PermGen space ",這裏的 「PermGen space」其實指的就是原來的方法區。不過方法區和「PermGen space」又有着本質的區別。前者是 JVM 的規範,然後者則是 JVM 規範的一種實現,而且只有 HotSpot 纔有 「PermGen space」,而對於其餘類型的虛擬機,如 JRockit(Oracle)、J9(IBM) 並無「PermGen space」。因爲方法區主要存儲類的相關信息,因此對於動態生成類的狀況比較容易出現永久代的內存溢出。最典型的場景就是,在 jsp 頁面比較多的狀況,容易出現永久代內存溢出
元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存,但能夠經過如下參數來指定元空間的大小:
-XX:MetaspaceSize,初始空間大小,達到該值就會觸發垃圾收集進行類型卸載,同時GC會對該值進行調整:若是釋放了大量的空間,就適當下降該值;若是釋放了不多的空間,那麼在不超過MaxMetaspaceSize時,適當提升該值。
-XX:MaxMetaspaceSize,最大空間,默認是沒有限制的。
除了上面兩個指定大小的選項之外,還有兩個與 GC 相關的屬性:
-XX:MinMetaspaceFreeRatio,在GC以後,最小的Metaspace剩餘空間容量的百分比,減小爲分配空間所致使的垃圾收集
-XX:MaxMetaspaceFreeRatio,在GC以後,最大的Metaspace剩餘空間容量的百分比,減小爲釋放空間所致使的垃圾收集
----------------------------------------------------------------