對於JVM記憶體模型的理解(對比jdk1.7與1.8)
首先介紹一下java虛擬機器規範所規定的java記憶體模型:
1.程式計數器(java記憶體模型中唯一不會發生oom的空間),負責記錄正在執行的虛擬機器位元組碼地址,如果是native方法,則計數器值為空,執行緒私有區
2.java虛擬機器棧,生命週期與執行緒相同。描述java方法執行的記憶體模型,每個方法執行時都會建立一個幀棧,用於儲存區域性變量表,運算元棧,動態連結,方法出口等資訊。區域性變量表存放了java的基本資料型別,物件引用等資訊。執行緒私有區
3.本地方法棧,與虛擬棧大致相同,主要為native方法服務
4.堆,堆是jvm記憶體管理的最大的一塊區域,此記憶體區域的唯一目的就是存放物件的例項,所有物件例項與陣列都要在堆上分配記憶體。它也是垃圾收集器的主要管理區域。java對可以處於物理上不連續的空間,只要邏輯上是連續的即可。執行緒共享的區域
5.方法區,用於儲存已被虛擬機器載入的類資訊,常量,即時編譯後的程式碼等。jvm規範把它描述為堆的一個邏輯部分。jdk8之前,大多數人習慣稱之為永久代,因為hotspot團隊把GC分代擴充套件至方法區。但是在jdk1.8已經徹底的剔除了永久代的概念,並用元空間來代替它。元空間不屬於jvm記憶體的一部分,它直接存在於本機記憶體中。而將常量池移到堆中
方法區與永久代的區別?
方法區只是JVM規範定義,而永久代為具體的實現,元空間也是方法區在jdk1.8中的一種實現。
為什麼廢除永久代?
1.官方文件:移除永久代是為融合HotSpot JVM與 JRockit VM而做出的努力,因為JRockit沒有永久代,不需要配置永久代
2..PermGen很難調整,PermGen中類的元資料資訊在每次FullGC的時候可能被收集,但成績很難令人滿意。
而且應該為PermGen分配多大的空間很難確定,因為PermSize的大小依賴於很多因素,比如JVM載入的class總數,常量池的大小,方法的大小等。
並且永久代記憶體經常不夠用發聲記憶體洩露。