1:是什麼
- 是各個線程共享的內存區域,它⽤於存儲已被虛擬機加載的類信息、常量、靜態變量、即時 編譯器編譯後的代碼等數據
- 什麼是類信息:類版本號、⽅法、接⼝
- 方法區(Method Area)存儲的類信息
對每個加載的類型(類class、接口interface、枚舉enum、註解annotation),JVM必須在方法區中存儲以下類型信息:
這個類型的完整有效名稱(全名=包名.類名)
這個類型直接父類的完整有效名稱( java.lang.Object除外,其他類型若沒有聲明父類,默認父類是Object)
這個類型的修飾符(public、abstract、final的某個子集)
這個類型直接接口的一個有序列表
除此之外還方法區(Method Area)存儲類信息還有類型的常量池( constant pool),域(Field)信息,方法(Method)信息,除了常量外的所有靜態(static)變量
2 方法區(Method Area)存儲的常量
static final修飾的成員變量都存儲於 方法區(Method Area)中
2.1方法區(Method Area)存儲的靜態變量
靜態變量又稱爲類變量,類中被static修飾的成員變量都是靜態變量(類變量)靜態變量之所以又稱爲類變量,是因爲靜態變量和類關聯在一起,隨着類的加載而存在於方法區(而不是堆中)
八種基本數據類型(byte、short、int、long、float、double、char、boolean)的靜態變量會在方法區開闢空間,並將對應的值存儲在方法方法區,對於引用類型的靜態變量如果未用new關鍵字爲引用類型的靜態變量分配對象(如:static Object obj;)那麼對象的引用obj會存儲在方法區中,併爲其指定默認值null;若,對於引用類型的靜態變量如果用new關鍵字爲引用類型的靜態變量分配對象(如:static Person person = new Person();),那麼對象的引用person 會存儲在方法區中,並且該對象在堆中的地址也會存儲在方法區中(注意此時靜態變量只存儲了對象的堆地址,而對象本身仍在堆內存中);這個過程還涉及到靜態變量初始化問題
3 方法區(Method Area)存儲的方法(Method)
程序運行時會加載類編譯生成的字節碼,這個過程中靜態變量(類變量)和靜態方法及普通方法對應的字節碼加載到方法區。但是!!!方法區中沒有實例變量,這是因爲,類加載先於對應類對象的產生,而實例變量是和對象關聯在一起的,對象存放在堆裏面,所以方法區中沒有實例變量靜態變量(類變量)和靜態方法及普通方法在方法區(Method Area)存儲方式是有區別的
此部分內容參考:https://blog.csdn.net/u013241673/article/details/78574770
2:爲什麼?
- 內存中存放類信息、靜態變量等數據,屬於線程共享的⼀塊區域
- Hotspot使⽤永久代來實現⽅法區 JRockit、IBM J9VM Java堆⼀樣管理這部分內存
3:特點?
- 在JDK1.6及之前,運行時常量池是方法區的一個部分,同時方法區裏面存儲了類的元數據信息、靜態變量、即時編譯器編譯後的代碼(比如spring 使用IOC或者AOP創建bean時,或者使用cglib,反射的形式動態生成class信息等)等。
- 在JDK1.7及以後,JVM已經將運行時常量池從方法區中移了出來,在JVM堆開闢了一塊區域存放常量池。並⾮數據進⼊了⽅法區就如永久代的名字⼀樣“永久”存在了。這區域的內存回收⽬標主要是針對常量池的回收和對類型的卸載
- ⽅法區也會拋出OutofMemoryError,當它⽆法滿⾜內存分配需求時