1. 程式人生 > >性能測試三十四:jvm內存結構(棧、堆、永久代)

性能測試三十四:jvm內存結構(棧、堆、永久代)

內容 清理 配置 線程 通過 棧內存 所有 不足 會有

Java內存管理機制

Java采用了自動管理內存的方式
Java程序是運行在Jvm之中的
Java的跨平臺的基於Jvm的跨平臺特性
內存的分配和對象的創建是在Jvm中
用戶可以通過一系列參數來配置Jvm

Jvm運行時區域

做性能測試經常接觸到的三個地方:方法區、虛擬機棧、堆

技術分享圖片

jvm主要內存結構(簡化版):

永久代即上面的方法區

占用內存大小排序:堆內存 > 永久代 > 棧內存

技術分享圖片

一:棧內存(虛擬機棧)

特點:

1、線程私有

  每個線程都有一塊自己獨有的內存,如果有10個線程,則會產生10個棧內存,100個線程則100個棧內存


2、生命周期和線程相同

  線程的生命周期:當執行到main方法的時候,就會給這個線程分配一塊棧內存,然後這個main方法會一直擁有這塊內存,當main方法裏面的代碼執行完畢,線程就結束了,分配的這塊內存就被回收了

技術分享圖片

3、主要存放內容
  1.基本數據類型(int,char,float,double…)
  2.對象的引用,指向了對象在堆內存中起始地址,凡是定義的變量和new的對象的變量,都在棧內存裏面放著

技術分享圖片

  3.通過-Xss參數配置

    因為機器內存是固定的,所以如果這個參數配的越大,就導致並發線程數越少(如內存1G,每個線程配1M,則最多只能起1024個線程),所以一般棧內存的單位是K,如128K、256K都可以,取決於線程裏面代碼的長度,代碼越長就需要越多的內存

二:堆內存-heap

堆內存構成
  新生代:包括三塊區域,eden、from survivor(s0)、to survivor(s1)
  老年代:old gen

Object o = new Object()
其中,o存放在棧內存中,new Object()存放在堆內存中,變量o是Object對象的引用,o上存放了Object對象占用內存的起始地址

1.堆內存是Jvm中空間最大的區域
2.所有線程共享堆
3.所有的數組以及內存對象的實例都在此區域分配
4.堆內存大小通過參數進行配置
  -Xmx:最大堆內存
  -Xms:最小堆內存

堆內存是公有的,存放真正的對象,因為真正的對象有很多屬性和信息,比較大,而棧內存比較小,所以放在堆內存中

技術分享圖片

技術分享圖片

New generation:新生代 / 年輕代

  新創建的對象,就放在eden區裏面,當多線程運行起來以後,每秒鐘都會有大量的對象被創建,而eden的容量有限,總有被放滿的時候,當eden區滿之後,會掃描eden+s0或者eden+s1,看有沒有還存活(有用的,代碼還沒執行完,需要用到)的對象(這裏以eden+s1為例),掃描完成後,會把eden+s1裏面還有用的、存活著的對象復制到s0裏面,並清空eden+s1,達到釋放內存的目的,此時eden區任然每秒鐘會產生大量的對象,過一段時間又會滿,此時,s1是空的,則會掃描eden+s0,將eden+s0裏面還存活的對象復制到s1裏面,清空eden+s0······一直如此循環,所以s0和s1永遠有個區域是空的,用於準備存放存活著的對象

  如果以10為單位的話,一般eden:s0:s1的比例是8:1:1

Old generation:老年代生代 / 老生代

  由於eden+s0/s1占了9/10,而要把存活下來的對象放到s0/s1,也就是說要把9/10裏面的一部分放到1/10的空間裏面,所以很有可能放不下,這個時候,新生代裏面的空間已經不足了,所以會把存活的對象放到老年代裏面,清空整個新生代空間(eden+s0+s1)

  在新生代做叠代掃描的時候,會給每個對象打個標記,當同一個對象的標記達到15次都還是存活狀態,則此對象不再參與新生代的叠代,直接放到老年代空間(如,jmeter運行5分鐘,腳本裏面的前置條件,則會存活5分鐘到結束才失效)

  所以老年代裏面放的都是長期有效的對象

  當老年代空間也滿的時候,會觸發一次整個堆內存的清理(新生代+老年代),同樣的,把有用的對方放在老年代,其他空間全部清空,達到釋放空間的目的

三:永久代-PermGen(方法區)(jdk1.8以後叫元空間)

永久代也叫(Method Area):

只要程序一運行起來,永久代裏面的數據就已經固定了,比如一個類裏面,定義了多少靜態變量、常量,是固定的
各線程共享,主方法區要存放類信息、常量、靜態變量,如:public static int a = 10
永久代裏面放的都是些固定的、不變的數據,所以垃圾回收行為比較少見,當進程結束的時候,才做回收操作

Jvm結構總結


年輕代 = Eden+Survivor
Survivor = From Space(s0) + To Space(s1)
年輕代 = Eden+From Space+To Space
堆內存 = 年輕代+老年代
堆內存=Eden+From Space+To Space+老年代
jvm=棧+堆+永久代

性能測試三十四:jvm內存結構(棧、堆、永久代)