Tomcat如何檢測記憶體流失

來源:互聯網
上載者:User

標籤:

一般情況下,如果我們重啟web應用是通過重啟tomcat的話,則不存在記憶體流失問題。但如果不重啟tomcat而對web應用進行重載入則可能會導致記憶體流失,因為重載入後有可能會導致原來的某些記憶體無法讓GC回收,例如web應用使用了JDBC,驅動會進行註冊,當web應用停止時沒有反註冊就會導致記憶體流失。

看看是什麼原因導致tomcat記憶體流失的。這個要從熱部署開始說起,因為tomcat提供了不必重啟容器而只需重啟web應用以達到熱部署的功能,其實現是通過定義一個WebappClassLoader類載入器,當熱部署時就將原來的類載入器廢棄並重新執行個體化一個WebappClassLoader類載入器。但這種方式可能存在記憶體流失問題,因為ClassLoader是一個結構複雜的對象,導致它不能被GC回收的可能性比較多,除了對ClassLoader對象有引用可能導致其無法回收,還可能對其載入的中繼資料(方法、類、欄位等)有引用都會導致無法被GC回收。

如,tomcat的資源由不同類載入器載入,這裡只看BootstrapClassLoader和WebappClassLoader兩個類載入器,BootstrapClassLoader負責載入rt.jar包的java.sql.DriverManager,WebappClassLoader負責載入web應用中的mysql驅動包,其中有一個很重要的步驟是mysql的驅動類需要註冊到DriverManager中,即DriverManager.registerDriver(new Driver()),它由mysql驅動包自動完成。這樣一來當web應用進行熱部署操作時,沒有將mysql的Driver從DriverManager中反註冊掉的話,則會導致整個WebappClassLoader回收不了,造成記憶體流失。

接著看tomcat如何對此記憶體流失進行監控的,要判斷WebappClassLoader會不會導致記憶體流失只需判斷WebappClassLoader有沒有被GC回收即可。在Java中有一種引用叫弱引用,它能很好判斷WebappClassLoader有沒有被GC回收,被弱引用關聯的對象只能生存到下一次記憶體回收發生之前,即如果某WebappClassLoader對象只被某弱引用關聯,則它會在下次記憶體回收時被回收,但如果WebappClassLoader對象除了被弱引用關聯外還被其他對象強引用,那麼WebappClassLoader對象是不會被回收的,根據這些條件就可以判斷是否有WebappClassLoader記憶體流失了。

Tomcat的實現是通過WeakHashMap來實現弱引用的,只需將WebappClassLoader對象put到WeakHashMap中,例如weakMap.put(“a”,webappClassLoader),當webappClassLoader及其包含的元素沒有被其它任何類載入器中的元素引用到時,JVM發生記憶體回收時則會把webappClassLoader對象回收。

簡單的實現代碼大致如下:

public class MemoryLeakTest{private Map<ClassLoader, String> childClassLoaders = new WeakHashMap<ClassLoader, String>();public String[] findReloadedContextMemoryLeaks() {        System.gc();        List<String> result = new ArrayList<String>();        for (Map.Entry<ClassLoader, String> entry : childClassLoaders.entrySet()) {            ClassLoader cl = entry.getKey();            if (!((WebappClassLoader) cl).isStarted()) {                result.add(entry.getValue());            }        }        return result.toArray(new String[result.size()]);    }}

使用一個WeakHashMap用於跟蹤WebappClassLoader,在尋找記憶體流失之前會先強制調用System.gc();進行一次記憶體回收,保證沒問題的WebappClassLoader都被回收掉,這時如果還有WebappClassLoader的狀態是非started(正常啟動的都為started,關閉了的則為非started)的,則是未被記憶體回收的WebappClassLoader,屬於記憶體流失的。

喜歡java的朋友可以加個好友:

Tomcat如何檢測記憶體流失

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.