Jvm內存結構

棧區

  1. 程序計數器:較小的內存空間, 當前線程執行的字節碼的行號指示器;各線程之間獨立存儲,互不影響;唯一無內存溢出的區域;
  2. java棧:線程私有,它的生命週期與線程相同,它描述的就是java方法執行的內存模型,每個方法在執行的同時都會創建一個棧幀用於存儲局部變量表,操作數棧,動態鏈接,方法出口等信息。方法的執行就對應著棧幀在虛擬機棧中入棧和出棧的過程;棧裡面存放著各種基本數據類型和對象的引用;
  3. 本地方法棧:本地方法棧保存的是native方法的信息,當一個JVM創建的線程調用native方法 後,JVM不再為其在虛擬機棧中創建棧幀,JVM只是簡單地動態鏈接並直接調用native方法

堆區

  1. 堆:Java堆是需要重點關注的一塊區域,因為涉及到內存的分配(new關鍵字,反射等)與回收(回收算法,收集器等);
  2. 方法區:也叫永久區,用於存儲已經被虛擬機加載的類信息,常量,靜態變 量,即時編譯器編譯後的代碼等數據。
  3. 運行時常量池:運行時常量池是方法區的一部分,用於存放編譯期生成的各種字面量和符號引用。

直接內存

不是虛擬機運行時數據區的一部分,也不是java虛擬機規範中定義的內存區域;如果使用了NIO,這塊區域會被頻繁使用,在java堆內可以用directByteBuffer對象直接引用並操作;這塊內存不受java堆大小限制,但受本機總內存的限制,可以通過MaxDirectMemorySize來設置(默認與堆內存最大值一樣),所以也會出現OOM異常;

堆和棧的區別

  1. 功能 棧是以棧幀的方式存儲方法調用的過程,並存儲方法調用過程中基本數據類型的變量以及對象的引用變量,其內存分配在棧上,變量出了作用域就會自動釋放;

    堆內存用來存儲Java中的對象。無論是成員變量,局部變量,還是類變量,它們指向的對象都存儲在堆內存中;

  2. 線程獨享還是共享 棧內存歸屬於單個線程,每個線程都會有一個棧內存,其存儲的變量只能在其所屬線程中可見,即棧內存可以理解成線程的私有內存。

    堆內存中的對象對所有線程可見。堆內存中的對象可以被所有線程訪問。

  3. 空間大小:棧的內存要遠遠小於堆內存;可以通過-Xss選項設置棧內存的大小。-Xms選項設置堆的開始時的大小,-Xmx選項設置堆的最大值

注意:

  1. 永久代來存儲類信息、常量、靜態變量等數據不是個好主意, 很容易遇到內存溢出的問題,因此在JDK8的實現中將類的元數據放入元空間(直接內存),可以使用MaxMetaspaceSize對元數據區大小進行調整; 將字符串池和類的靜態變量放入java堆中.
  2. 對永久代進行調優是很困難的,同時將元空間與堆的垃圾回收進行了隔離,避免永久代引發的Full GC和OOM等問題
Jvm內存結構


分享到:


相關文章: