<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Live a simple life

    沉默(zhu_xing@live.cn)
    隨筆 - 48, 文章 - 0, 評(píng)論 - 132, 引用 - 0
    數(shù)據(jù)加載中……

    【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析

            現(xiàn)在,網(wǎng)上關(guān)于討論P(yáng)ermGen OOM的資料很多,但是深入分析PermGen區(qū)域內(nèi)存溢出原因的資料很少。本篇文章嘗試全面分析一下PermGen OOM的原因,其中涉及到了Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)、類(lèi)型裝載、類(lèi)型卸載等,測(cè)試代碼涉及到了JMX協(xié)議。相關(guān)前提知識(shí)如下:
           1、Java類(lèi)加載的基本原理
           2、Java類(lèi)型卸載相關(guān)的知識(shí),http://m.tkk7.com/zhuxing/archive/2008/07/24/217285.html
           3、簡(jiǎn)要了解JMX協(xié)議,有關(guān)JMX協(xié)議可以參加sun公司發(fā)布的技術(shù)規(guī)范,對(duì)JMX協(xié)議做一定的了解對(duì)理解Java性能監(jiān)控和調(diào)優(yōu)功能的實(shí)現(xiàn)原理有很大幫助。

            
           【虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)介紹】
        
    本部分將對(duì)Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)做一個(gè)簡(jiǎn)單的介紹,著重說(shuō)明PermGen區(qū)域(永久存儲(chǔ)區(qū))存放的內(nèi)容,并對(duì)運(yùn)行時(shí)數(shù)據(jù)區(qū)的訪問(wèn)方式做一個(gè)歸納說(shuō)明,為后面深入分析類(lèi)型卸載和PermGen OOM做鋪墊。為了更具有通用性,本部分將更多關(guān)注虛擬機(jī)協(xié)議本身,可能和具體的虛擬機(jī)實(shí)現(xiàn)有少許的出入。

            【運(yùn)行時(shí)數(shù)據(jù)區(qū)分類(lèi)】

            Java虛擬機(jī)的運(yùn)行時(shí)數(shù)據(jù)區(qū)一般分類(lèi)如下(不一定是物理劃分):   

  •     堆:主要存放對(duì)象實(shí)例,線程共享
  •     棧:主要存儲(chǔ)特定線程的方法調(diào)用狀態(tài),線程獨(dú)占
  •     本地方法棧:存儲(chǔ)本地方法的調(diào)用狀態(tài),線程獨(dú)占
  •     PC寄存器:學(xué)過(guò)操作系統(tǒng)課程的都知道,線程獨(dú)占
  •     方法區(qū):主要存儲(chǔ)了類(lèi)型信息,線程共享 

            方法區(qū)可以簡(jiǎn)單的等價(jià)為所謂的PermGen區(qū)域(永久存儲(chǔ)區(qū)),在很多虛擬機(jī)相關(guān)的文檔中,也將其稱(chēng)之為"永久堆"(permanent heap),作為堆空間的一部分存在。介于此,我們可以簡(jiǎn)單說(shuō)明一下我們常用的幾個(gè)堆內(nèi)存配置的參數(shù)關(guān)系:
        *-XX: PermSize:*永久堆(Pergen區(qū)域)大小默認(rèn)值
        *-XX:MaxPermSize:*永久堆(Pergen區(qū)域)最大值
        *-Xms:*堆內(nèi)存大小默認(rèn)值
        *-Xmx:*堆內(nèi)存最大值

            【運(yùn)行時(shí)數(shù)據(jù)區(qū)訪問(wèn)方式總結(jié)】

        從開(kāi)發(fā)者角度,虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的訪問(wèn)方式簡(jiǎn)要?dú)w納如下:

  •     活動(dòng)的線程可以通過(guò)對(duì)應(yīng)的棧來(lái)訪問(wèn)運(yùn)行時(shí)數(shù)據(jù)區(qū)信息
  •     棧是堆訪問(wèn)的入口
  •     堆上Java.lang.Class實(shí)例是訪問(wèn)PermGen區(qū)域中類(lèi)型信息的入口 
             
    1. 一個(gè)類(lèi)型裝載之后會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的java.lang.Class實(shí)例,這個(gè)實(shí)例本身和普通對(duì)象實(shí)例一樣存儲(chǔ)于堆中,我覺(jué)得之所以說(shuō)是這是一種特殊的實(shí)例,某種程度上是因?yàn)槠涑洚?dāng)了訪問(wèn)PermGen區(qū)域中類(lèi)型信息的代理者。
    2. 圖中"Class類(lèi)型實(shí)例"和"類(lèi)加載器實(shí)例"分別是A類(lèi)型對(duì)應(yīng)的java.lang.Class實(shí)例和加載A類(lèi)型的類(lèi)加載器實(shí)例。
    3. 只要是有active的對(duì)象實(shí)例句柄,就能夠訪問(wèn)到對(duì)應(yīng)的Class類(lèi)型實(shí)例和類(lèi)加載器實(shí)例,分別通過(guò)Object.getClass()方法和Class.getClassLoader()方法。
    4. 只要是有active的Class類(lèi)型實(shí)例句柄,就能夠訪問(wèn)到對(duì)應(yīng)的類(lèi)加載器實(shí)例。

            【PermGen內(nèi)存溢出深入分析】

            【前提知識(shí)】    

  •     由不同的類(lèi)加載器實(shí)例加載的類(lèi)型可以等價(jià)為完全不同的類(lèi)型,哪怕時(shí)同一類(lèi)型類(lèi)加載器的不同實(shí)例加載的,都會(huì)在PermGen區(qū)域分配相應(yīng)的空間來(lái)存儲(chǔ)類(lèi)型信息
  •     新類(lèi)型加載時(shí),會(huì)在PermGen區(qū)域申請(qǐng)相應(yīng)的空間來(lái)存儲(chǔ)類(lèi)型信息,類(lèi)型被卸載后,PermGen區(qū)域上的垃圾收集會(huì)釋放對(duì)應(yīng)的內(nèi)存空間。PermGen區(qū)域和普通的堆空間一樣,也遵循垃圾收集的規(guī)律,所以,網(wǎng)上很多資料種關(guān)于PermGen區(qū)域空間的大小是只增不減的說(shuō)法是不正確的,后面會(huì)用相應(yīng)的測(cè)試代碼來(lái)驗(yàn)證和分析。
  •     一種類(lèi)型被卸載的前提條件是:加載此類(lèi)型的類(lèi)加載器實(shí)例變?yōu)椴豢蛇_(dá)(unreachable)狀態(tài),虛擬機(jī)協(xié)議中對(duì)應(yīng)描述如下:
        A class or interface may be unloaded if and only if its class loader is unreachable. The bootstrap class loader is always reachable; as a result, system classes may never be unloaded.
    關(guān)于實(shí)例的*unreachable*狀態(tài),大致可以理解為不能通過(guò)特定活動(dòng)線程對(duì)應(yīng)的棧出發(fā)通過(guò)引用計(jì)算來(lái)到達(dá)對(duì)應(yīng)的實(shí)例,虛擬機(jī)協(xié)議中對(duì)應(yīng)描述如下:
        _A reachable object is any object that can be accessed in any potential continuing
    computation from any live thread._
        結(jié)合上面的[虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的介紹|],可以得出結(jié)論:類(lèi)型對(duì)應(yīng)的普通實(shí)例、類(lèi)型對(duì)應(yīng)的java.lang.Class實(shí)例、加載此類(lèi)型的ClassLoader實(shí)例,三者中有任何一種或者多種是reachable狀態(tài)的,那么此類(lèi)型就不可能被卸載。
  •     JMX協(xié)議提供了相應(yīng)的API接口,用來(lái)在運(yùn)行時(shí)查詢(xún)當(dāng)前虛擬機(jī)實(shí)例的內(nèi)存使用和類(lèi)型加載等信息。這也是很多Java性能監(jiān)控和分析工具的基礎(chǔ),后面的測(cè)試程序中也有相應(yīng)的代碼使用了JMX協(xié)議。

            
                【測(cè)試程序分析】       

  • 虛擬機(jī)器參數(shù)設(shè)置如下:
        -XX: PermSize=4M -XX:MaxPermSize=4M -verbose -verbose:gc
        設(shè)置-verbose參數(shù)是為了獲取類(lèi)型加載和卸載的信息
        設(shè)置-verbose:gc是為了獲取垃圾收集的相關(guān)信息
  • 在D:/classes目錄下有一個(gè)簡(jiǎn)單的類(lèi)型ZhuXing對(duì)應(yīng)的class字節(jié)碼,測(cè)試代碼中用URLClassLoader來(lái)加載此類(lèi)型

     

            【測(cè)試程序一:模擬PermGen OOM】

     1 try {
     2    //準(zhǔn)備url
     3    URL url = new File("D:/classes").toURL();
     4    URL[] urls = {url};
     5 
     6    //獲取有關(guān)類(lèi)型加載的JMX接口
     7     ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
     8 
     9    //用于緩存類(lèi)加載器
    10     List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
    11 
    12    while (true) {
    13      //加載類(lèi)型并緩存類(lèi)加載器實(shí)例
    14        ClassLoader classLoader = new URLClassLoader(urls);
    15       classLoaders.add(classLoader);
    16       classLoader.loadClass("ZhuXing");
    17 
    18      //顯示數(shù)量信息(共加載過(guò)的類(lèi)型數(shù)目,當(dāng)前還有效的類(lèi)型數(shù)目,已經(jīng)被卸載的類(lèi)型數(shù)目)
    19       System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
    20 System.out.println("active: " + loadingBean.getLoadedClassCount());
    21      System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
    22    }
    23 catch (Exception e) {
    24    e.printStackTrace();
    25 }
    26 
    27 

         【測(cè)試程序一分析
    運(yùn)行測(cè)試程序一,輸出信息如下(摘取了部分):
    ......
    [Loaded ZhuXing from [file:/D:/classes/]]
    total: 2914
    active: 2914
    unloaded: 0
    [Loaded ZhuXing from [file:/D:/classes/]]
    total: 2915
    active: 2915
    unloaded: 0
    [Full GC 4852K->4852K(8720K), 0.0993780 secs]
    [Full GC 4852K->4829K(8720K), 0.0999775 secs]
    [Full GC 4829K->4829K(8720K), 0.0989805 secs]
    [Full GC 4829K->4829K(8720K), 0.0997261 secs]
    ......
    Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
    ......
    [Unloading class ZhuXing]
    ......
    [Loaded java.lang.Shutdown from D:\eos6\jdk1.5.0_09\jre\lib\rt.jar]
    [Loadedjava.lang.Shutdown$Lockfrom D:\eos6\jdk1.5.0_09\jre\lib\rt.jar

        
            針對(duì)以上摘錄的虛擬機(jī)器運(yùn)行時(shí)信息,分析結(jié)論如下:

  •     一直在持續(xù)的加載類(lèi)型ZhuXing,而且一直沒(méi)有卸載,直到PermGen OOM發(fā)生。類(lèi)型ZhuXing無(wú)法卸載的原因,前面說(shuō)明過(guò),是由于對(duì)應(yīng)的類(lèi)加載器實(shí)例一直是reachaable狀態(tài),緩存對(duì)象實(shí)例或者java.lang.Class實(shí)例同樣可以達(dá)到無(wú)法卸載類(lèi)型的效果。
  •     在PermGen OOM發(fā)生前,虛擬機(jī)進(jìn)行了非常頻繁的垃圾收集,效果甚微
  •     在PermGen OOM發(fā)生后,卸載了類(lèi)型ZhuXing,當(dāng)前虛擬機(jī)實(shí)例退出


            【測(cè)試程序二:PermGen區(qū)域垃圾收集】

                和測(cè)試程序一相比,刪除了類(lèi)加載器實(shí)例緩存的代碼
     1 try {
     2      //準(zhǔn)備url
     3      URL url = new File("D:/classes").toURL();
     4      URL[] urls = {url};
     5 
     6      //獲取有關(guān)類(lèi)型加載的JMX接口
     7       ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
     8 
     9      while (true) {
    10      //加載類(lèi)型,不緩存類(lèi)加載器實(shí)例
    11       new URLClassLoader(urls).loadClass("ZhuXing");
    12      //顯示數(shù)量信息(共加載過(guò)的類(lèi)型數(shù)目,當(dāng)前還有效的類(lèi)型數(shù)目,已經(jīng)被卸載的類(lèi)型數(shù)目)
    13       System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
    14      System.out.println("active: " + loadingBean.getLoadedClassCount());
    15      System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
    16     }
    17 catch (Exception e) {
    18     e.printStackTrace();
    19 }
    20 
    21 

    測(cè)試程序二分析
    運(yùn)行測(cè)試程序二很長(zhǎng)時(shí)間,一直沒(méi)有發(fā)生PermGen OOM異常,輸出信息如下(摘取了部分):
    ...
    [Loaded ZhuXing from [file:/D:/classes/]]
    total: 19540
    active: 1052
    unloaded: 18488
    [Full GC 1563K->259K(2112K), 0.1758958 secs]
    ......
    [Unloading class ZhuXing]
    [Unloading class ZhuXing]
    [Unloading class ZhuXing]
    ......
    [GC 1968K->1563K(2112K), 0.0025266 secs]
    ......
    [Loaded ZhuXing from [file:/D:/classes/]]
    total: 21098
    active: 440
    unloaded: 20658
    ...
    針對(duì)以上摘錄的虛擬機(jī)器運(yùn)行時(shí)信息,分析結(jié)論如下:

    1. 類(lèi)型ZhuXing在頻繁被加載的同時(shí),也在頻繁被卸載,當(dāng)被加載的類(lèi)型達(dá)到了21098時(shí),并沒(méi)有發(fā)生PermGen OOM,20658已經(jīng)被卸載,堆內(nèi)存的占用比測(cè)試代碼一中小的多
    2. 中間進(jìn)行的垃圾并不是特別頻繁,但是垃圾收集的效果較為明顯
    3. 類(lèi)型被卸載之后,伴隨著PermGen區(qū)域上的垃圾收集和新類(lèi)型的不斷被加載,PermGen區(qū)域中類(lèi)型信息占有的堆內(nèi)存大小在有序的增大減小

            【PermGen OOM原因總結(jié)】
                通過(guò)上面的[測(cè)試程序分析|],我們發(fā)現(xiàn)PermGen OOM發(fā)生的原因和類(lèi)型裝載、類(lèi)型卸載有直接的關(guān)系,可以對(duì)PermGen OOM發(fā)生的原因做如下大致的總結(jié):
            1、PermGen區(qū)域分配的堆空間過(guò)小,可以通過(guò)設(shè)置-XX: PermSize參數(shù)和-XX:MaxPermSize參數(shù)來(lái)解決。
  •         2、類(lèi)型卸載不及時(shí),過(guò)時(shí)無(wú)效的類(lèi)型信息占用了空間,我們不妨稱(chēng)其為"永久堆"的內(nèi)存泄漏,需要通過(guò)深入分析類(lèi)型卸載的原理來(lái)尋找對(duì)應(yīng)的防范措施


            【常見(jiàn)的類(lèi)加載器和類(lèi)型卸載的可能性總結(jié)】
            通過(guò)前面的討論,我們知道如果加載某種類(lèi)型的類(lèi)加載器實(shí)例沒(méi)有處于unreachable狀態(tài),則該類(lèi)型就不會(huì)被卸載,該類(lèi)型不被卸載,則對(duì)應(yīng)的類(lèi)型信息在PermGen區(qū)域中占有的堆內(nèi)存就不會(huì)被釋放。下面,針對(duì)典型的Java應(yīng)用分類(lèi),分析一下常用類(lèi)加載器加載的類(lèi)型被下載的可能性。

            【普通Java應(yīng)用】
            啟動(dòng)類(lèi)加載器:由于其負(fù)責(zé)加載虛擬機(jī)的核心類(lèi)型,所以由其加載的類(lèi)型在整個(gè)程序運(yùn)行期間不可能被卸載,對(duì)應(yīng)類(lèi)型信息占用的PermGen區(qū)域堆空間不可能得到釋放。
            擴(kuò)展類(lèi)加載器:負(fù)責(zé)加載JDK擴(kuò)展路徑下的類(lèi)型,擴(kuò)展類(lèi)加載器同時(shí)又作為系統(tǒng)類(lèi)加載器的父類(lèi)加載器,所以,由其加載的類(lèi)型在整個(gè)程序運(yùn)行期間基本上不可能被卸載,對(duì)應(yīng)類(lèi)型信息占用的PermGen區(qū)域堆空間基本不可能得到釋放。
            系統(tǒng)類(lèi)加載器:負(fù)責(zé)加載程序類(lèi)路徑上面的類(lèi)型,由其加載的類(lèi)型在整個(gè)程序運(yùn)行期間基本上不可能被卸載,對(duì)應(yīng)類(lèi)型信息占用的PermGen區(qū)域堆空間基本不可能得到釋放。
            用戶(hù)自定義類(lèi)加載器:對(duì)于其加載的類(lèi)型,滿(mǎn)足類(lèi)型卸載要求的可能性比較容易控制,只要是其實(shí)例本身處于unreachable狀態(tài),其加載的類(lèi)型會(huì)被卸載,PermGen區(qū)域中對(duì)應(yīng)的空間占有也會(huì)被釋放。


            【插件開(kāi)發(fā)】
            系統(tǒng)類(lèi)加載器:由于其負(fù)責(zé)加載虛擬機(jī)的核心類(lèi)型,所以由其加載的類(lèi)型在插件應(yīng)用運(yùn)行期間不可能被卸載,對(duì)應(yīng)類(lèi)型信息占用的PermGen區(qū)域堆空間不可能得到釋放。
            插件類(lèi)加載器:系統(tǒng)插件類(lèi)加載器負(fù)責(zé)加載OSGI實(shí)現(xiàn)的相關(guān)類(lèi)型,所以由其加載的類(lèi)型在插件應(yīng)用運(yùn)行期間不可能被卸載;用戶(hù)開(kāi)發(fā)的插件所使用的默認(rèn)插件類(lèi)加載器,和特定的插件本身進(jìn)行域綁定,插件之間存在一定的類(lèi)型引用關(guān)系,并且特定插件在整個(gè)插件應(yīng)用的運(yùn)行時(shí)被停止的可能性也很小,所以類(lèi)型卸載發(fā)生幾率極小。
            用戶(hù)自定義類(lèi)加載器:對(duì)于其加載的類(lèi)型,滿(mǎn)足類(lèi)型卸載要求的可能性比較容易控制,只要是其實(shí)例本身處于unreachable狀態(tài),其加載的類(lèi)型會(huì)被卸載,PermGen區(qū)域中對(duì)應(yīng)的空間占有也會(huì)被釋放。

            【PermGen內(nèi)存溢出的應(yīng)對(duì)措施】
         
    通過(guò)上面的PermGen OOM的原因的分析,不難看出對(duì)應(yīng)的應(yīng)對(duì)措施:

  •     合理的設(shè)置-XX: PermSize和-XX:MaxPermSize參數(shù)(主要的有效措施)
  •     有效的利用的虛擬機(jī)類(lèi)型卸載的機(jī)制(針對(duì)程序進(jìn)行調(diào)優(yōu))


            【合理設(shè)置參數(shù)(針對(duì)普通用戶(hù)和開(kāi)發(fā)者)】
            通過(guò)設(shè)置合理的XX: PermSize和-XX:MaxPermSize參數(shù)值是減少和有效避免PermGen OOM發(fā)生的最有效最主要的措施,尤其是針對(duì)普通用戶(hù)而言,這基本上是唯一的辦法。關(guān)于合理設(shè)置這兩個(gè)參數(shù),建議如下:

  •      XX: PermSize參數(shù)的設(shè)置盡量建立在基準(zhǔn)測(cè)試的基礎(chǔ)之上,可以利用監(jiān)控工具對(duì)穩(wěn)定運(yùn)行期間PermGen區(qū)域的大小進(jìn)行統(tǒng)計(jì),取合理的平均值。網(wǎng)上的很多資料中,建議XX: PermSize和XX:MaxPermSize設(shè)置為相同的數(shù)值,個(gè)人覺(jué)得這是不正確的,因?yàn)閮蓚€(gè)參數(shù)的出發(fā)點(diǎn)是不一樣的。XX: PermSize設(shè)置的過(guò)大肯定會(huì)在應(yīng)用運(yùn)行的大部分時(shí)間中浪費(fèi)堆內(nèi)存,有可能會(huì)明顯增加存放普通對(duì)象實(shí)例的堆空間的垃圾收集的次數(shù)。

  •     XX:MaxPermSize參數(shù)的設(shè)置應(yīng)該著眼于PermGen區(qū)域使用的峰值,因?yàn)檫@是避免PermGen OOM的最后一道屏障,其設(shè)置最好也是建立在性能監(jiān)控工具的統(tǒng)計(jì)結(jié)果之上。
  •     和虛擬機(jī)有關(guān)的性能參數(shù)較多的分為兩類(lèi),一類(lèi)是初始值或默認(rèn)值,一類(lèi)是峰值。如果該性能參數(shù)是會(huì)涉及到的虛擬機(jī)垃圾收集機(jī)制的,關(guān)于初始值或者默認(rèn)值的設(shè)置盡量要建立在測(cè)試基礎(chǔ)之上,盡量做到在單次垃圾收集時(shí)間和垃圾收集頻率之間保持一個(gè)平衡,否則很有可能適得其反。


             【有效利用虛擬機(jī)類(lèi)型卸載機(jī)制(針對(duì)開(kāi)發(fā)者)】
            此部分的建議可以作為開(kāi)發(fā)者進(jìn)行性能調(diào)優(yōu)或者日常開(kāi)發(fā)時(shí)候的參考,盡量能夠配合相應(yīng)的性能監(jiān)控工具進(jìn)行:   

  •     檢查是否由于程序設(shè)計(jì)本身上的缺陷,導(dǎo)致加載了大量實(shí)際上并不需要的類(lèi)型。較新版本的Java虛擬機(jī)實(shí)現(xiàn),一般都遵循動(dòng)態(tài)解析的建議,所以不是人為設(shè)計(jì)的缺陷,一般不會(huì)誘發(fā)加載了大量實(shí)際上并不需要的類(lèi)型。結(jié)合插件開(kāi)發(fā)的應(yīng)用場(chǎng)景,個(gè)人覺(jué)得插件功能模塊的劃分(其中包括了插件依賴(lài)關(guān)系的設(shè)計(jì)和有關(guān)擴(kuò)展點(diǎn)的擴(kuò)展收集等)和第三方j(luò)ar的使用可能是誘發(fā)此問(wèn)題的兩個(gè)重要根源。
  •     對(duì)象緩存的使用是否得當(dāng),通過(guò)前面的分析,我們知道這可能是導(dǎo)致類(lèi)型不能被卸載的重要原因。緩存的使用,既要認(rèn)識(shí)到其可以提高時(shí)間性能的有點(diǎn),也要分析其可能會(huì)給普通對(duì)象堆空間和PermGen區(qū)域造成的負(fù)擔(dān)。
  •     自定義類(lèi)加載器的合理使用,相關(guān)的幾個(gè)注意要點(diǎn)包括:
    1. 是否不恰當(dāng)?shù)睦玫念?lèi)型更新的特性,也就是說(shuō)是否對(duì)類(lèi)加載器實(shí)例的unreachable狀態(tài)做了有效的判斷。考慮如下場(chǎng)景,假設(shè)用戶(hù)開(kāi)發(fā)了一個(gè)自定義類(lèi)加載器來(lái)加載工程輸出目錄下的臨時(shí)類(lèi)型,對(duì)臨時(shí)類(lèi)型做了不必要的緩存,這肯定會(huì)導(dǎo)致所有被加載過(guò)的臨時(shí)類(lèi)型都不會(huì)得到卸載,會(huì)直接加重PermGen區(qū)域的負(fù)擔(dān)。
    2. 自定義類(lèi)加載器和其他已有類(lèi)加載器的協(xié)作關(guān)系是否合理,是否合理的利用了Java類(lèi)加載的雙親委派機(jī)制。我們知道,不同的類(lèi)加載器實(shí)例(哪怕是同一種類(lèi)加載器類(lèi)型的不同實(shí)例)加載的同一種自定義類(lèi)型在虛擬機(jī)內(nèi)部都會(huì)被放置到不同的命名空間中作為不同類(lèi)型來(lái)處理,所以合理的設(shè)置父類(lèi)加載器變得很重要,不合理的設(shè)置會(huì)導(dǎo)致大量不必要的"新"類(lèi)型被創(chuàng)造出來(lái),況且這些不必要的"新"類(lèi)型是否能夠被及時(shí)卸載還是個(gè)未知數(shù)。
  •     慎重檢查自定義類(lèi)加載器實(shí)例是否被不恰當(dāng)?shù)木彺媪耍虿谎远鳌?

    【后記】
    寫(xiě)這篇文章的初衷是為了深入的分析PermGen OOM發(fā)生的原因,在深入分析的基礎(chǔ)之上理解PermGen OOM的應(yīng)對(duì)措施,從"為什么會(huì)發(fā)生PermGen OOM"到"到底為什么會(huì)發(fā)生PermGen OOM"。希望對(duì)大家更深入的認(rèn)識(shí)PermGen OOM和PermGen OOM的應(yīng)對(duì)措施起到作用,謝謝!


  • 本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請(qǐng)注明出處,謝謝!

    posted on 2008-08-01 19:31 zhuxing 閱讀(4856) 評(píng)論(10)  編輯  收藏 所屬分類(lèi): Java

    評(píng)論

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    有筆誤
    系統(tǒng)類(lèi)加載器:由于其負(fù)責(zé)加載虛擬機(jī)的核心類(lèi)型
    這里不應(yīng)該是系統(tǒng)類(lèi)加載器吧,應(yīng)該是boostrap加載器。
    2008-08-01 20:40 | 鬼狗

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    @鬼狗

    是筆誤,因該是啟動(dòng)類(lèi)加載器,已經(jīng)修改
    2008-08-02 12:55 | zhuxing

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    樓主的圖掛了,用的是局域網(wǎng)
    2008-08-04 10:43 | d

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析[未登錄](méi)  回復(fù)  更多評(píng)論   

    樓主把圖片的問(wèn)題解決掉就好了
    2008-08-04 16:17 | mark

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    @mark
    圖片放上去了
    2008-08-08 10:23 | zhuxing

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    還是看不到圖片的 做個(gè)測(cè)試啊
    2008-08-30 19:52 | advincenting

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析[未登錄](méi)  回復(fù)  更多評(píng)論   

    老大..你的文章寫(xiě)的非常好..
    看了您的有關(guān) classLoader load & classLoader unload & PermGen OOM
    這幾篇..都非常不錯(cuò)哈..
    獲益良多..非常感謝..繼續(xù)支持你..
    2008-10-14 14:09 | qq

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    恩, 寫(xiě)的確實(shí)不錯(cuò), 這3篇文章...
    2008-10-14 14:12 | moxiso

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    寫(xiě)得不錯(cuò)!~
    2009-02-20 17:41 | Adam

    # re: 【原創(chuàng)】?jī)?nèi)存溢出之PermGen OOM深入分析  回復(fù)  更多評(píng)論   

    把簡(jiǎn)單問(wèn)題搞復(fù)雜了!·
    2009-06-18 10:44 | 式樣z
    主站蜘蛛池模板: 精品免费久久久久国产一区| 亚洲视频在线观看网站| 美女露隐私全部免费直播| 国外亚洲成AV人片在线观看| 亚洲免费一级视频| 97公开免费视频| 久久久久久国产精品免费免费男同 | 免费无遮挡无码视频在线观看| 亚洲国产精品无码AAA片| 成人A级毛片免费观看AV网站| 亚洲成人免费电影| 每天更新的免费av片在线观看| 99热这里有免费国产精品| 一级特黄aa毛片免费观看| 小日子的在线观看免费| 久久亚洲免费视频| 中文字幕在线免费观看| 日本免费xxxx| 成人免费午夜视频| 四虎1515hm免费国产| 99在线精品视频观看免费| xxxxxx日本处大片免费看| 久久不见久久见免费影院www日本 久久WWW免费人成—看片 | 免费观看无遮挡www的视频| 99久在线国内在线播放免费观看| 最近中文字幕高清免费中文字幕mv| 最近中文字幕大全中文字幕免费| 国产精品69白浆在线观看免费| 18禁超污无遮挡无码免费网站 | 亚洲一区二区三区免费视频| 亚洲人妻av伦理| 亚洲国产午夜福利在线播放| 亚洲永久无码3D动漫一区| 国产在线ts人妖免费视频| 国产h肉在线视频免费观看| 毛片免费观看的视频在线| 免费一级毛片一级毛片aa| 黑人大战亚洲人精品一区| 久久亚洲AV成人无码国产| 色噜噜亚洲男人的天堂| 亚洲嫩草影院久久精品|