java虛擬機器 jvm 方法區實戰
和java堆一樣,方法區是一塊所有執行緒共享的記憶體區域,用於儲存系統的類資訊,類的資訊有哪些呢。欄位、方法、常量池。方法區也有一塊記憶體區域所以方法區的記憶體大小,決定了系統可以包含多少個類,如果系統類太多,方法區記憶體不夠肯定會導致方法區溢位,虛擬機器同樣會丟擲記憶體溢位資訊。(記憶體溢位後面相關文章給大家總結)
jdk6和jdk7中,方法區可以理解為永久區(Perm).永久區可以使用引數-XX:PermSize和-XX:MaxPermSize制定。預設情況下-XX:MaxPermSize為64MB.如果你專案中使用代理模式或者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 初始永久區大小
-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中永久區被移除了,取而代之的是元資料區,可能方法區依賴
元資料區發生溢位,虛擬機器一樣丟擲異常,如下: