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 初始永久區大小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

到此這篇關於java虛擬機jvm方法區實例講解的文章就介紹到這瞭,更多相關java虛擬機 jvm 方法區實戰內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: