深入理解Java虛擬機---jdk1.8廢棄永久代的原因

方法區(Method Area)與Java堆一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載 的類型信息、常量、靜態變量、即時編譯器編譯後的代碼緩存等數據。雖然《Java虛擬機規範》中把 方法區描述爲堆的一個邏輯部分,但是它卻有一個別名叫作“非堆”(Non-Heap),目的是與Java堆區 分開來。說到方法區,不得不提一下“永久代”這個概念,尤其是在JDK 8以前,許多Java程序員都習慣在 HotSpot虛擬機上開發、部署程序,很多人都更願意把方法區稱呼爲“永久代”(Permanent Generation),或將兩者混爲一談。
本質上這兩者並不是等價的,因爲僅僅是當時的HotSpot虛擬機設 計團隊選擇把收集器的分代設計擴展至方法區,或者說使用永久代來實現方法區而已,這樣使得 HotSpot的垃圾收集器能夠像管理Java堆一樣管理這部分內存,省去專門爲方法區編寫內存管理代碼的 工作。但是對於其他虛擬機實現,譬如BEA JRockit、IBM J9等來說,是不存在永久代的概念的。
原則 上如何實現方法區屬於虛擬機實現細節,不受《Java虛擬機規範》管束,並不要求統一。但現在回頭 來看,當年使用永久代來實現方法區的決定並不是一個好主意,
1.永久代這種設計導致了Java應用更容易遇到 內存溢出的問題(永久代有-XX:MaxPermSize的上限,即使不設置也有默認大小,而J9和JRockit只要 沒有觸碰到進程可用內存的上限,例如32位系統中的4GB限制,就不會出問題),而且有極少數方法 (例如String::intern())會因永久代的原因而導致不同虛擬機下有不同的表現。
2.優秀功能移植有困難,當Oracle收購BEA獲得了 JRockit的所有權後,準備把JRockit中的優秀功能,譬如Java Mission Control管理工具,移植到HotSpot 虛擬機時,但因爲兩者對方法區實現的差異而面臨諸多困難。考慮到HotSpot未來的發展,在JDK 6的 時候HotSpot開發團隊就有放棄永久代,逐步改爲採用本地內存(Native Memory)來實現方法區的計 劃了,到了JDK 7的HotSpot,已經把原本放在永久代的字符串常量池、靜態變量等移出,而到了 JDK 8,終於完全廢棄了永久代的概念,改用與JRockit、J9一樣在本地內存中實現的元空間(Meta- space)來代替,把JDK 7中永久代還剩餘的內容(主要是類型信息)全部移到元空間中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章