1. 程式人生 > >java虛擬機器 jvm 方法區實戰

java虛擬機器 jvm 方法區實戰

java堆一樣,方法區是一塊所有執行緒共享的記憶體區域,用於儲存系統的類資訊,類的資訊有哪些呢。欄位、方法、常量池。方法區也有一塊記憶體區域所以方法區的記憶體大小,決定了系統可以包含多少個類,如果系統類太多,方法區記憶體不夠肯定會導致方法區溢位,虛擬機器同樣會丟擲記憶體溢位資訊。(記憶體溢位後面相關文章給大家總結)

jdk6jdk7中,方法區可以理解為永久區(Perm).永久區可以使用引數-XX:PermSize-XX:MaxPermSize制定。預設情況下-XX:MaxPermSize64MB.如果你專案中使用代理模式或者CGLIB的話可能在執行的時候生成大量的類,如果這樣,需要設定一下永久區的大小,防止永久區記憶體溢位。

CGLIB會在後面專門的章節和代理模式一起講解。(這個系列專注的是JVM的講解)

使用下面程式碼:

for (int i = 0; i <10000; i++) {
CglibWapper c=new CglibWapper("cn.springok.perm"+i)
}


程式碼解釋:會根據傳入的引數動態生成一個類以及類的例項。因為物件例項化,類的欄位、方法、常量池儲存在方法區,因此操作會佔用一定記憶體的。

大量的類可能導致方法區溢位,使用下面的引數執行程式碼:

-XX:PermSize=10M  -XX:MaxPermSize=10M -XX:PrintGCDetails

引數說明:

-XX:PermSize=10M  初始永久區大小

10M

-XX:MaxPermSize 方法區最大記憶體10M

-XX:PrintGCDetails 列印日誌詳情。

執行程式部分輸出如下:

 compacting perm gen  total 86272K, used 86136K [0x44600000, 0x49a40000, 0x64600000) 

   the space 86272K,  99% used [0x44600000, 0x49a1e2f8, 0x49a1e400, 0x49a40000) 

系統記憶體溢位了,擴大-XX:MaxPermSize值,可以生成更多的類。

可以使用工具Visual VM觀察方法區的具體使用情況。

 

需要注意一點:

jdk8中永久區被移除了,取而代之的是元資料區,可能方法區依賴

jvm的記憶體吧。元資料區可以使用-XX:MaxMetaspaceSize制定,跟之前版本的-XX:MaxPermSize一樣,分配的值越多,就可以支援更多的類。不同的是元資料區是堆外直接記憶體,與方法永久區不同,在不指定大小的情況下,虛擬機器會耗盡所有可用的系統記憶體。

元資料區發生溢位,虛擬機器一樣丟擲異常,如下:

java.lang.OutOfMemoryError Metaspace