java中的Person是什么

這篇文章將為大家詳細(xì)講解有關(guān)java中的Person是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

在八公山等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司 網(wǎng)站設(shè)計(jì)制作按需開發(fā)網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都全網(wǎng)營(yíng)銷推廣,成都外貿(mào)網(wǎng)站制作,八公山網(wǎng)站建設(shè)費(fèi)用合理。

方法區(qū)

這次所講述的是運(yùn)行時(shí)數(shù)據(jù)區(qū)的最后一個(gè)部分

java中的Person是什么

從線程共享與否的角度來(lái)看

java中的Person是什么

ThreadLocal:如何保證多個(gè)線程在并發(fā)環(huán)境下的安全性?典型應(yīng)用就是數(shù)據(jù)庫(kù)連接管理,以及會(huì)話管理

一 棧、堆、方法區(qū)的交互關(guān)系

下面就涉及了對(duì)象的訪問定位

java中的Person是什么

  • Person:存放在元空間,也可以說(shuō)方法區(qū)

  • person:存放在Java棧的局部變量表中

  • new Person():存放在Java堆中

二 方法區(qū)的理解

《Java虛擬機(jī)規(guī)范》中明確說(shuō)明:“盡管所有的方法區(qū)在邏輯上是屬于堆的一部分,但一些簡(jiǎn)單的實(shí)現(xiàn)可能不會(huì)選擇去進(jìn)行垃圾收集或者進(jìn)行壓縮?!钡珜?duì)于HotSpotJVM而言,方法區(qū)還有一個(gè)別名叫做Non-Heap(非堆),目的就是要和堆分開。

所以,方法區(qū)看作是一塊獨(dú)立于Java堆的內(nèi)存空間。

java中的Person是什么

方法區(qū)主要存放的是 Class,而堆中主要存放的是 實(shí)例化的對(duì)象

  • 方法區(qū)(Method Area)與Java堆一樣,是各個(gè)線程共享的內(nèi)存區(qū)域。

  • 方法區(qū)在JVM啟動(dòng)的時(shí)候被創(chuàng)建,并且它的實(shí)際的物理內(nèi)存空間中和Java堆區(qū)一樣都可以是不連續(xù)的。

  • 方法區(qū)的大小,跟堆空間一樣,可以選擇固定大小或者可擴(kuò)展。

  • 方法區(qū)的大小決定了系統(tǒng)可以保存多少個(gè)類,如果系統(tǒng)定義了太多的類,導(dǎo)致方法區(qū)溢出,虛擬機(jī)同樣會(huì)拋出內(nèi)存溢出錯(cuò)誤:ava.lang.OutofMemoryError:PermGen space或者java.lang.OutOfMemoryError:Metaspace

    • 加載大量的第三方的jar包

    • Tomcat部署的工程過多(30~50個(gè))

    • 大量動(dòng)態(tài)的生成反射類

  • 關(guān)閉JVM就會(huì)釋放這個(gè)區(qū)域的內(nèi)存。

HotSpot中方法區(qū)的演進(jìn)

  • 在jdk7及以前,習(xí)慣上把方法區(qū),稱為永久代。jdk8開始,使用元空間取代了永久代。

    • JDK 1.8后,元空間存放在堆外內(nèi)存中

  • 本質(zhì)上,方法區(qū)和永久代并不等價(jià)。僅是對(duì)hotspot而言的?!禞ava虛擬機(jī)規(guī)范》對(duì)如何實(shí)現(xiàn)方法區(qū),不做統(tǒng)一要求。例如:BEAJRockit / IBM J9 中不存在永久代的概念。

現(xiàn)在來(lái)看,當(dāng)年使用永久代,不是好的idea。導(dǎo)致Java程序更容易o(hù)om(超過-XX:MaxPermsize上限)

java中的Person是什么

  • 而到了JDK8,終于完全廢棄了永久代的概念,改用與JRockit、J9一樣在本地內(nèi)存中實(shí)現(xiàn)的元空間(Metaspace)來(lái)代替

    java中的Person是什么

  • 元空間的本質(zhì)和永久代類似,都是對(duì)JVM規(guī)范中方法區(qū)的實(shí)現(xiàn)。不過元空間與永久代最大的區(qū)別在于:元空間不在虛擬機(jī)設(shè)置的內(nèi)存中,而是使用本地內(nèi)存

  • 永久代、元空間二者并不只是名字變了,內(nèi)部結(jié)構(gòu)也調(diào)整了

  • 根據(jù)《Java虛擬機(jī)規(guī)范》的規(guī)定,如果方法區(qū)無(wú)法滿足新的內(nèi)存分配需求時(shí),將拋出OOM異常

三 設(shè)置方法區(qū)大小與OOM

  • 方法區(qū)的大小不必是固定的,JVM可以根據(jù)應(yīng)用的需要?jiǎng)討B(tài)調(diào)整。

JKD7 及以前

  • 通過-xx:Permsize來(lái)設(shè)置永久代初始分配空間。默認(rèn)值是20.75M

  • -XX:MaxPermsize來(lái)設(shè)定永久代最大可分配空間。32位機(jī)器默認(rèn)是64M,64位機(jī)器模式是82M

  • 當(dāng)JVM加載的類信息容量超過了這個(gè)值,會(huì)報(bào)異常OutofMemoryError:PermGen space。

java中的Person是什么

JDK8以后

  • 元數(shù)據(jù)區(qū)大小可以使用參數(shù) -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize指定

  • 默認(rèn)值依賴于平臺(tái)。windows下,-XX:MetaspaceSize是21M,-XX:MaxMetaspaceSize的值是-1,即沒有限制。

  • 與永久代不同,如果不指定大小,默認(rèn)情況下,虛擬機(jī)會(huì)耗盡所有的可用系統(tǒng)內(nèi)存。如果元數(shù)據(jù)區(qū)發(fā)生溢出,虛擬機(jī)一樣會(huì)拋出異常OutOfMemoryError:Metaspace

  • -XX:MetaspaceSize:設(shè)置初始的元空間大小。對(duì)于一個(gè)64位的服務(wù)器端JVM來(lái)說(shuō),其默認(rèn)的-xx:MetaspaceSize值為21MB。這就是初始的高水位線,一旦觸及這個(gè)水位線,F(xiàn)ull GC將會(huì)被觸發(fā)并卸載沒用的類(即這些類對(duì)應(yīng)的類加載器不再存活)然后這個(gè)高水位線將會(huì)重置。新的高水位線的值取決于GC后釋放了多少元空間。如果釋放的空間不足,那么在不超過MaxMetaspaceSize時(shí),適當(dāng)提高該值。如果釋放空間過多,則適當(dāng)降低該值。

  • 如果初始化的高水位線設(shè)置過低,上述高水位線調(diào)整情況會(huì)發(fā)生很多次。通過垃圾回收器的日志可以觀察到FullGC多次調(diào)用。為了避免頻繁地GC,建議將-XX:MetaspaceSize設(shè)置為一個(gè)相對(duì)較高的值。

如何解決這些OOM

  • 要解決OOM異?;騢eap space的異常,一般的手段是首先通過內(nèi)存映像分析工具(如Eclipse Memory Analyzer)對(duì)dump出來(lái)的堆轉(zhuǎn)儲(chǔ)快照進(jìn)行分析,重點(diǎn)是確認(rèn)內(nèi)存中的對(duì)象是否是必要的,也就是要先分清楚到底是出現(xiàn)了內(nèi)存泄漏(Memory Leak)還是內(nèi)存溢出(Memory Overflow)

    • 內(nèi)存泄漏就是 有大量的引用指向某些對(duì)象,但是這些對(duì)象以后不會(huì)使用了,但是因?yàn)樗鼈冞€和GC ROOT有關(guān)聯(lián),所以導(dǎo)致以后這些對(duì)象也不會(huì)被回收,這就是內(nèi)存泄漏的問題

  • 如果是內(nèi)存泄漏,可進(jìn)一步通過工具查看泄漏對(duì)象到GC Roots的引用鏈。于是就能找到泄漏對(duì)象是通過怎樣的路徑與GCRoots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無(wú)法自動(dòng)回收它們的。掌握了泄漏對(duì)象的類型信息,以及GCRoots引用鏈的信息,就可以比較準(zhǔn)確地定位出泄漏代碼的位置。

  • 如果不存在內(nèi)存泄漏,換句話說(shuō)就是內(nèi)存中的對(duì)象確實(shí)都還必須存活著,那就應(yīng)當(dāng)檢查虛擬機(jī)的堆參數(shù)(-Xmx與-Xms),與機(jī)器物理內(nèi)存對(duì)比看是否還可以調(diào)大,從代碼上檢查是否存在某些對(duì)象生命周期過長(zhǎng)、持有狀態(tài)時(shí)間過長(zhǎng)的情況,嘗試減少程序運(yùn)行期的內(nèi)存消耗。

四 方法區(qū)的內(nèi)部結(jié)構(gòu)

java中的Person是什么

《深入理解Java虛擬機(jī)》書中對(duì)方法區(qū)(Method Area)存儲(chǔ)內(nèi)容描述如下:它用于存儲(chǔ)已被虛擬機(jī)加載的類型信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼緩存等。

java中的Person是什么

類型信息

對(duì)每個(gè)加載的類型(類class、接口interface、枚舉enum、注解annotation),JVM必須在方法區(qū)中存儲(chǔ)以下類型信息:

  1. 這個(gè)類型的完整有效名稱(全名=包名.類名)

  2. 這個(gè)類型直接父類的完整有效名(對(duì)于interface或是java.lang.object,都沒有父類)

  3. 這個(gè)類型的修飾符(public,abstract,final的某個(gè)子集)

  4. 這個(gè)類型直接接口的一個(gè)有序列表

域(Field)信息

  • JVM必須在方法區(qū)中保存類型的所有域的相關(guān)信息以及域的聲明順序。

  • 域的相關(guān)信息包括:域名稱、域類型、域修飾符(public,private,protected,static,final,volatile,transient的某個(gè)子集)

方法(Method)信息

JVM必須保存所有方法的以下信息,同域信息一樣包括聲明順序:

  • 方法名稱

  • 方法的返回類型(或void)

  • 方法參數(shù)的數(shù)量和類型(按順序)

  • 方法的修飾符(public,private,protected,static,final,synchronized,native,abstract的一個(gè)子集)

  • 方法的字節(jié)碼(bytecodes)、 操作數(shù)棧、局部變量表及大?。╝bstract和native方法除外)

  • 異常表(abstract和native方法除外)

每個(gè)異常處理的開始位置、結(jié)束位置、代碼處理在程序計(jì)數(shù)器中的偏移地址、被捕獲的異常類的常量池索引

non-final的類變量

  • 靜態(tài)變量和類關(guān)聯(lián)在一起,隨著類的加載而加載,他們成為類數(shù)據(jù)在邏輯上的一部分

  • 類變量被類的所有實(shí)例共享,即使沒有類實(shí)例時(shí),你也可以訪問它

/**
 * non-final的類變量
 *
 */
public class MethodAreaTest {
    public static void main(String[] args) {
        Order order = new Order();
        order.hello();
        System.out.println(order.count);
    }
}
class Order {
    public static int count = 1;
    public static final int number = 2;
    public static void hello() {
        System.out.println("hello!");
    }
}

如上代碼所示,即使我們把order設(shè)置為null,也不會(huì)出現(xiàn)空指針異常

全局常量 同時(shí)使用 static final 進(jìn)行修飾

  • 被聲明為final的類變量的處理方法則不同,每個(gè)全局常量在編譯的時(shí)候就會(huì)被分配了。

運(yùn)行時(shí)常量池 VS 常量池

java中的Person是什么

  • 方法區(qū),內(nèi)部包含了運(yùn)行時(shí)常量池

  • 字節(jié)碼文件,內(nèi)部包含了常量池

  • 要弄清楚方法區(qū),需要理解清楚C1assFile,因?yàn)榧虞d類的信息都在方法區(qū)。

  • 要弄清楚方法區(qū)的運(yùn)行時(shí)常量池,需要理解清楚classFile中的常量池。

常量池

java中的Person是什么

  • 一個(gè)有效的字節(jié)碼文件中除了包含類的版本信息、字段、方法以及接口等描述符信息外,還包含一項(xiàng)信息就是常量池表(Constant Pool Table),包括各種字面量和對(duì)類型、域和方法的符號(hào)引用

為什么需要常量池?

一個(gè)java源文件中的類、接口,編譯后產(chǎn)生一個(gè)字節(jié)碼文件。而Java中的字節(jié)碼需要數(shù)據(jù)支持,通常這種數(shù)據(jù)會(huì)很大以至于不能直接存到字節(jié)碼里,換另一種方式,可以存到常量池,這個(gè)字節(jié)碼包含了指向常量池的引用。在動(dòng)態(tài)鏈接的時(shí)候會(huì)用到運(yùn)行時(shí)常量池,之前有介紹。

比如:如下的代碼:

public class SimpleClass {
    public void sayHello() {
        System.out.println("hello");
    }
}

雖然上述代碼只有194字節(jié),但是里面卻使用了String、System、PrintStream及Object等結(jié)構(gòu)。這里的代碼量其實(shí)很少了,如果代碼多的話,引用的結(jié)構(gòu)將會(huì)更多,這里就需要用到常量池了。

常量池中有什么
  • 數(shù)量值

  • 字符串值

  • 類引用

  • 字段引用

  • 方法引用

例如下面這段代碼

public class MethodAreaTest2 {
    public static void main(String args[]) {
        Object obj = new Object();
    }
}

將會(huì)被翻譯成如下字節(jié)碼

new #2  
dup
invokespecial
小結(jié)
  • 常量池、可以看做是一張表,虛擬機(jī)指令根據(jù)這張常量表找到要執(zhí)行的類名、方法名、參數(shù)類型、字面量等類型

運(yùn)行時(shí)常量池

  • 運(yùn)行時(shí)常量池(Runtime Constant Pool)是方法區(qū)的一部分。

  • 常量池表(Constant Pool Table)是Class文件的一部分,用于存放編譯期生成的各種字面量與符號(hào)引用,這部分內(nèi)容將在類加載后存放到方法區(qū)的運(yùn)行時(shí)常量池中。

  • 運(yùn)行時(shí)常量池,在加載類和接口到虛擬機(jī)后,就會(huì)創(chuàng)建對(duì)應(yīng)的運(yùn)行時(shí)常量池。

  • JVM為每個(gè)已加載的類型(類或接口)都維護(hù)一個(gè)常量池。池中的數(shù)據(jù)項(xiàng)像數(shù)組項(xiàng)一樣,是通過索引訪問的。

  • 運(yùn)行時(shí)常量池中包含多種不同的常量,包括編譯期就已經(jīng)明確的數(shù)值字面量,也包括到運(yùn)行期解析后才能夠獲得的方法或者字段引用。此時(shí)不再是常量池中的符號(hào)地址了,這里換為真實(shí)地址。

    • 運(yùn)行時(shí)常量池,相對(duì)于Class文件常量池的另一重要特征是:具備動(dòng)態(tài)性。

  • 運(yùn)行時(shí)常量池類似于傳統(tǒng)編程語(yǔ)言中的符號(hào)表(symboltable),但是它所包含的數(shù)據(jù)卻比符號(hào)表要更加豐富一些。

  • 當(dāng)創(chuàng)建類或接口的運(yùn)行時(shí)常量池時(shí),如果構(gòu)造運(yùn)行時(shí)常量池所需的內(nèi)存空間超過了方法區(qū)所能提供的最大值,則JVM會(huì)拋outofMemoryError異常。

五 方法區(qū)使用舉例

如下代碼

public class MethodAreaDemo {
    public static void main(String args[]) {
        int x = 500;
        int y = 100;
        int a = x / y;
        int b = 50;
        System.out.println(a+b);
    }
}

字節(jié)碼執(zhí)行過程展示

java中的Person是什么

首先現(xiàn)將操作數(shù)500放入到操作數(shù)棧中

java中的Person是什么

然后存儲(chǔ)到局部變量表中

java中的Person是什么

然后重復(fù)一次,把100放入局部變量表中,最后再將變量表中的500 和 100 取出,進(jìn)行操作

java中的Person是什么

將500 和 100 進(jìn)行一個(gè)除法運(yùn)算,在把結(jié)果入棧

java中的Person是什么

在最后就是輸出流,需要調(diào)用運(yùn)行時(shí)常量池的常量

java中的Person是什么

最后調(diào)用invokevirtual(虛方法調(diào)用),然后返回

java中的Person是什么

返回時(shí)

java中的Person是什么

程序計(jì)數(shù)器始終計(jì)算的都是當(dāng)前代碼運(yùn)行的位置,目的是為了方便記錄 方法調(diào)用后能夠正常返回,或者是進(jìn)行了CPU切換后,也能回來(lái)到原來(lái)的代碼進(jìn)行執(zhí)行。

六 方法區(qū)的演進(jìn)細(xì)節(jié)

  1. 首先明確:只有Hotspot才有永久代。BEA JRockit、IBMJ9等來(lái)說(shuō),是不存在永久代的概念的。原則上如何實(shí)現(xiàn)方法區(qū)屬于虛擬機(jī)實(shí)現(xiàn)細(xì)節(jié),不受《Java虛擬機(jī)規(guī)范》管束,并不要求統(tǒng)一

  2. Hotspot中方法區(qū)的變化:

JDK1.6及以前有永久代,靜態(tài)變量存儲(chǔ)在永久代上
JDK1.7有永久代,但已經(jīng)逐步 “去永久代”,字符串常量池,靜態(tài)變量移除,保存在堆中
JDK1.8及之后無(wú)永久代,類型信息,字段,方法,常量保存在本地內(nèi)存的元空間,但字符串常量池、靜態(tài)變量仍然在堆中。

JDK6的時(shí)候

java中的Person是什么

JDK7的時(shí)候

java中的Person是什么

JDK8的時(shí)候,元空間大小只受物理內(nèi)存影響

java中的Person是什么

為什么永久代要被元空間替代?

JRockit是和HotSpot融合后的結(jié)果,因?yàn)镴Rockit沒有永久代,所以他們不需要配置永久代

  • 隨著Java8的到來(lái),HotSpot VM中再也見不到永久代了。但是這并不意味著類的元數(shù)據(jù)信息也消失了。這些數(shù)據(jù)被移到了一個(gè)與堆不相連的本地內(nèi)存區(qū)域,這個(gè)區(qū)域叫做元空間(Metaspace)。

  • 由于類的元數(shù)據(jù)分配在本地內(nèi)存中,元空間的最大可分配空間就是系統(tǒng)可用內(nèi)存空間,這項(xiàng)改動(dòng)是很有必要的,原因有:

1)為永久代設(shè)置空間大小是很難確定的。

在某些場(chǎng)景下,如果動(dòng)態(tài)加載類過多,容易產(chǎn)生Perm區(qū)的oom。比如某個(gè)實(shí)際Web工 程中,因?yàn)楣δ茳c(diǎn)比較多,在運(yùn)行過程中,要不斷動(dòng)態(tài)加載很多類,經(jīng)常出現(xiàn)致命錯(cuò)誤。

“Exception in thread‘dubbo client x.x connector'java.lang.OutOfMemoryError:PermGen space”

而元空間和永久代之間最大的區(qū)別在于:元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。 因此,默認(rèn)情況下,元空間的大小僅受本地內(nèi)存限制。

2)對(duì)永久代進(jìn)行調(diào)優(yōu)是很困難的。

  • 主要是為了降低Full GC

有些人認(rèn)為方法區(qū)(如HotSpot虛擬機(jī)中的元空間或者永久代)是沒有垃圾收集行為的,其實(shí)不然。《Java虛擬機(jī)規(guī)范》對(duì)方法區(qū)的約束是非常寬松的,提到過可以不要求虛擬機(jī)在方法區(qū)中實(shí)現(xiàn)垃圾收集。事實(shí)上也確實(shí)有未實(shí)現(xiàn)或未能完整實(shí)現(xiàn)方法區(qū)類型卸載的收集器存在(如JDK11時(shí)期的ZGC收集器就不支持類卸載)。 一般來(lái)說(shuō)這個(gè)區(qū)域的回收效果比較難令人滿意,尤其是類型的卸載,條件相當(dāng)苛刻。但是這部分區(qū)域的回收有時(shí)又確實(shí)是必要的。以前sun公司的Bug列表中,曾出現(xiàn)過的若干個(gè)嚴(yán)重的Bug就是由于低版本的HotSpot虛擬機(jī)對(duì)此區(qū)域未完全回收而導(dǎo)致內(nèi)存泄漏

方法區(qū)的垃圾收集主要回收兩部分內(nèi)容:常量池中廢棄的常量和不在使用的類型

StringTable為什么要調(diào)整位置

  • JDK7中將StringTable放到了堆空間中。因?yàn)橛谰么幕厥招屎艿?,在full gc的時(shí)候才會(huì)觸發(fā)。而FULL  GC是老年代的空間不足、永久代不足時(shí)才會(huì)觸發(fā)。

  • 這就導(dǎo)致StringTable回收效率不高。而我們開發(fā)中會(huì)有大量的字符串被創(chuàng)建,回收效率低,導(dǎo)致永久代內(nèi)存不足。放到堆里,能及時(shí)回收內(nèi)存。

靜態(tài)變量存放在那里?

靜態(tài)引用對(duì)應(yīng)的對(duì)象實(shí)體始終都存在堆空間

可以使用 jhsdb.exe,需要在jdk9的時(shí)候才引入的

staticobj隨著Test的類型信息存放在方法區(qū),instanceobj隨著Test的對(duì)象實(shí)例存放在Java堆,localobject則是存放在foo()方法棧幀的局部變量表中。

java中的Person是什么

測(cè)試發(fā)現(xiàn):三個(gè)對(duì)象的數(shù)據(jù)在內(nèi)存中的地址都落在Eden區(qū)范圍內(nèi),所以結(jié)論:只要是對(duì)象實(shí)例必然會(huì)在Java堆中分配。

接著,找到了一個(gè)引用該staticobj對(duì)象的地方,是在一個(gè)java.lang.Class的實(shí)例里,并且給出了這個(gè)實(shí)例的地址,通過Inspector查看該對(duì)象實(shí)例,可以清楚看到這確實(shí)是一個(gè)java.lang.Class類型的對(duì)象實(shí)例,里面有一個(gè)名為staticobj的實(shí)例字段:

java中的Person是什么

從《Java虛擬機(jī)規(guī)范》所定義的概念模型來(lái)看,所有Class相關(guān)的信息都應(yīng)該存放在方法區(qū)之中,但方法區(qū)該如何實(shí)現(xiàn),《Java虛擬機(jī)規(guī)范》并未做出規(guī)定,這就成了一件允許不同虛擬機(jī)自己靈活把握的事情。JDK7及其以后版本的HotSpot虛擬機(jī)選擇把靜態(tài)變量與類型在Java語(yǔ)言一端的映射class對(duì)象存放在一起,存儲(chǔ)于Java堆之中,從我們的實(shí)驗(yàn)中也明確驗(yàn)證了這一點(diǎn)

六 方法區(qū)的垃圾回收

有些人認(rèn)為方法區(qū)(如Hotspot虛擬機(jī)中的元空間或者永久代)是沒有垃圾收集行為的,其實(shí)不然。《Java虛擬機(jī)規(guī)范》對(duì)方法區(qū)的約束是非常寬松的,提到過可以不要求虛擬機(jī)在方法區(qū)中實(shí)現(xiàn)垃圾收集。事實(shí)上也確實(shí)有未實(shí)現(xiàn)或未能完整實(shí)現(xiàn)方法區(qū)類型卸載的收集器存在(如JDK11時(shí)期的zGC收集器就不支持類卸載)。

一般來(lái)說(shuō)這個(gè)區(qū)域的回收效果比較難令人滿意,尤其是類型的卸載,條件相當(dāng)苛刻。但是這部分區(qū)域的回收有時(shí)又確實(shí)是必要的。以前sun公司的Bug列表中,曾出現(xiàn)過的若干個(gè)嚴(yán)重的Bug就是由于低版本的HotSpot虛擬機(jī)對(duì)此區(qū)域未完全回收而導(dǎo)致內(nèi)存泄漏。

方法區(qū)的垃圾收集主要回收兩部分內(nèi)容:常量池中廢棄的常量和不再使用的類型。

  • 先來(lái)說(shuō)說(shuō)方法區(qū)內(nèi)常量池之中主要存放的兩大類常量:字面量和符號(hào)引用。字面量比較接近Java語(yǔ)言層次的常量概念,如文本字符串、被聲明為final的常量值等。而符號(hào)引用則屬于編譯原理方面的概念,包括下面三類常量:

    • 類和接口的全限定名

    • 字段的名稱和描述符

    • 方法的名稱和描述符

  • HotSpot虛擬機(jī)對(duì)常量池的回收策略是很明確的,只要常量池中的常量沒有被任何地方引用,就可以被回收。

  • 回收廢棄常量與回收J(rèn)ava堆中的對(duì)象非常類似。(關(guān)于常量的回收比較簡(jiǎn)單,重點(diǎn)是類的回收)

  • 判定一個(gè)常量是否“廢棄”還是相對(duì)簡(jiǎn)單,而要判定一個(gè)類型是否屬于“不再被使用的類”的條件就比較苛刻了。需要同時(shí)滿足下面三個(gè)條件:

    • 該類所有的實(shí)例都已經(jīng)被回收,也就是Java堆中不存在該類及其任何派生子類的實(shí)例。

    • 加載該類的類加載器已經(jīng)被回收,這個(gè)條件除非是經(jīng)過精心設(shè)計(jì)的可替換類加載器的場(chǎng)景,如OSGi、JSP的重加載等,否則通常是很難達(dá)成的。

    • 該類對(duì)應(yīng)的java.lang.C1ass對(duì)象沒有在任何地方被引用,無(wú)法在任何地方通過反射訪問該類的方法。I

  • Java虛擬機(jī)被允許對(duì)滿足上述三個(gè)條件的無(wú)用類進(jìn)行回收,這里說(shuō)的僅僅是“被允許”,而并不是和對(duì)象一樣,沒有引用了就必然會(huì)回收。關(guān)于是否要對(duì)類型進(jìn)行回收,HotSpot虛擬機(jī)提供了-Xnoclassgc參數(shù)進(jìn)行控制,還可以使用-verbose:class 以及 -XX:+TraceClass-Loading、-XX:+TraceClassUnLoading查看類加載和卸載信息

  • 在大量使用反射、動(dòng)態(tài)代理、CGLib等字節(jié)碼框架,動(dòng)態(tài)生成JSP以及oSGi這類頻繁自定義類加載器的場(chǎng)景中,通常都需要Java虛擬機(jī)具備類型卸載的能力,以保證不會(huì)對(duì)方法區(qū)造成過大的內(nèi)存壓力。

總結(jié)

java中的Person是什么

關(guān)于java中的Person是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

新聞名稱:java中的Person是什么
本文鏈接:http://bm7419.com/article30/iihdso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站策劃、網(wǎng)站內(nèi)鏈、用戶體驗(yàn)、網(wǎng)站改版、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名