方法區和永久代


1.方法區和永久代的關系

  涉及到內存模型時,往往會提到永久代,那么它和方法區又是什么關系呢?《Java虛擬機規范》只是規定了有方法區這么個概念和它的作用,並沒有規定如何去實現它。那么,在不同的 JVM 上方法區的實現肯定是不同的了。 同時大多數用的JVM都是Sun公司的HotSpot。在HotSpot上把GC分代收集擴展至方法區,或者說使用永久代來實現方法區。因此,我們得到了結論,永久代是HotSpot的概念,方法區是Java虛擬機規范中的定義,是一種規范,而永久代是一種實現,一個是標准一個是實現。其他的虛擬機實現並沒有永久帶這一說法。在1.7之前在(JDK1.2 ~ JDK6)的實現中,HotSpot 使用永久代實現方法區,HotSpot 使用 GC分代來實現方法區內存回收,可以使用如下參數來調節方法區的大小:

  方法區和永久代的關系很像Java中接口和類的關系,永久代是HotSpot虛擬機對虛擬機規范中方法區的一種實現方式。

JDK1.8之前調節方法區大小:

  -XX:PermSize=N //方法區(永久代)初始大小

  -XX:MaxPermSize=N //方法區(永久代)最大大小,超出這個值將會拋出OutOfMemoryError 

JDK1.8開始方法區(HotSpot的永久代)被徹底刪除了,取而代之的是元空間,元空間直接使用的是本機內存。參數設置:

  -XX:MetaspaceSize=N //設置Metaspace的初始(和最小大小)

  -XX:MaxMetaspaceSize=N //設置Metaspace的最大大小

 

2.元空間
      對於Java8, HotSpots取消了永久代,那么是不是也就沒有方法區了呢?當然不是,方法區是一個規范,規范沒變,它就一直在。那么取代永久代的就是元空間。它可永久代有什么不同的?存儲位置不同,永久代物理是是堆的一部分,和新生代,老年代地址是連續的,而元空間屬於本地內存;存儲內容不同,元空間只存儲類和類加載器的元數據信息,靜態變量和常量池等並入堆中。相當於永久代的數據被分到了堆和元空間中。

3.永久代和元空間內存使用上的差異:

  Java虛擬機規范中只定義了方法區用於存儲已被虛擬機加載的類信息、常量、靜態變量和即時編譯后的代碼等數據

    1)jdk1.7開始符號引用存儲在native heap中,字符串常量和靜態類型變量存儲在普通的堆區中,但分離的並不徹底,此時永久代中還保存另一些與類的元數據無關的雜項

    2)jdk8后HotSpot 原永久代中存儲的類的元數據將存儲在metaspace中,而類的靜態變量和字符串常量將放在Java堆中,metaspace是方法區的一種實現,只不過它使用的不是虛擬機內的內存,而是本地內存。在元空間中保存的數據比永久代中純粹很多,就只是類的元數據,這些信息只對編譯期或JVM的運行時有用。

    3)永久代有一個JVM本身設置固定大小上線,無法進行調整,而元空間使用的是直接內存,受本機可用內存的限制,並且永遠不會得到java.lang.OutOfMemoryError。
    4) 符號引用沒有存在元空間中,而是存在native heap中,這是兩個方式和位置,不過都可以算作是本地內存,在虛擬機之外進行划分,沒有設置限制參數時只受物理內存大小限制,即只有占滿了操作系統可用內存后才OOM。

 
4.關鍵詞分析:
  1)元數據:
    元數據是關於數據的數據。在編程語言上下文中,元數據是添加到程序元素如方法、字段、類和包上的額外信息。對數據進行說明描述的數據
     注解Annotation就是java平台的元數據
      元數據以標簽的形式存在於Java代碼中。 
      元數據描述的信息是類型安全的,即元數據內部的字段都是有明確類型的。 
      元數據需要編譯器之外的工具額外的處理用來生成其它的程序部件。 
       元數據可以只存在於Java源代碼級別,也可以存在於編譯之后的Class文件內部。
  ·  在注解誕生之前,程序的元數據存在的形式僅限於xml 部署描述文件、java注釋或javadoc,
      但注解可以提供更多功能,它不僅包含元數據,還能作用於運行期,注解解析器能夠使用注解決定處理流程
  2)符號引用
     符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能夠無歧義的定位到目標即可。比如org.simple.People類引用了                    org.simple.Language類,在編譯時People類並不知道Language類的實際內存地址,因此只能使用符號org.simple.Language(假設是這個,當然實際中是由類似於     CONSTANT_Class_info的常量來表示的)來表示Language類的地址。
       在JVM中類加載過程中,在解析階段,Java虛擬機會把類的二級制數據中的符號引用替換為直接引用。
  3)直接引用可以是
    1)直接指向目標的指針(比如,指向“類型”【Class對象】、類變量、類方法的直接引用可能是指向方法區的指針)
    2)相對偏移量(比如,指向實例變量、實例方法的直接引用都是偏移量)
    3)一個能間接定位到目標的句柄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM