您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Tomcat與內存泄露處理的示例分析,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
但是隨著開發經歷的增長,已經開發過應用的增多,應用內需要加載的 class 增多,經常就會遇到內存溢出(OOM)。或者更確切的說,因為加載 class 的增多導致的內存溢出是java.lang.OutOfMemoryError: PermGen space
此時,解決OOM的方式一般是
分析應用的代碼寫的是否有問題,可以通過一些工具觀察應用內占用內存較多的 class 類型 (比如通過 JVisualVM 來分析Java七武器系列多情環 --多功能Profiling工具 JVisual VM,或者通過MAT來分析)
修改 JVM啟動參數,增大關于 Perm Gen 的配置。
在 Tomcat 這一類的 應用服務器中,由于其做為應用的容器運行,可能自身的Perm Gen 占用并不多,但需要考慮部署到容器中的應用占用。有些應用依賴了大量的第三方類庫,也有一些應用會在運行時動態生成大量的 class,這些內容的加載,都容易導致 Perm Gen 的 OOM。
對于 OOM 的處理,內部會在啟動時占用一小塊內存,在 OOM 產生的時候釋放掉來臨時緩解一下,這種稱為oomParachute。前面寫過一篇介紹的文章(預防OOM,Tomcat是這樣做的)。
除此之外,Tomcat 在 manager 應用中還提供了發現內存泄漏的功能。
圖上說明寫的明白,該功能主要用于分析在應用停止、重部署、解除部署時是否造成了內存泄漏。
在請求后,manager的上方信息顯示區域會提示當前是否有應用造成的內存泄漏。
但需要注意的是此功能會觸發一次 Full GC 的執行,代碼中使用的是 System.gc(),在生產環境中如果使用需要謹慎。
那么,在什么情況下會導致所謂的應用內存泄漏呢?
我們都知道, 為了實現應用間的 class 隔離, Tomcat 對于每個應用,都會單獨使用一個 WebappClassLoader,這樣,多個應用間即使都使用到一個 類庫的不同版本,也不會相互影響造成沖突。 (參考前面的文章:Tomcat類加載器以及應用間class隔離與共享, 類加載器與類沖突)
但是,在這種情況下,當一個應用已經執行了停止操作,或者執行了重部署操作,此時是會生成一個新的 classLoader 來加載新部署的應用類信息。
我們知道,在 Java 中,類與類之間是存在引用關系的,類似于強引用,弱引用,幻影引用,用來在GC時將一些不需要的 class 回收掉,騰出空間。按理說之前的 classLoader 本應該被垃圾回收,但在某些時候,由于一些類之前的引用關系導致該 classLoader,以及其加載的一系列 class 文件, 都不能被標識為垃圾,此時這些 class 依然駐留在 Perm Gen,隨著應用多次啟停,多次重部署之后,出現了 Perm Gen 的 OOM。
一般以下類庫的使用容易導致 class loader 逃過垃圾回收,產生內存泄漏:
JDBC driver 注冊
一些 logging 框架
沒有移除的 ThreadLocal的使用
未停止的 Thread
此外,一些 Java API 的使用也容易導致此問題,例如
javax.imageio API
XML 解析
RMI 使用
由于這些容易占用 classLoader,導致其不能被回收,如果這些 class 交給各個應用的類加載器進行加載,就會使得 Perm Gen 中這些類越來越多,從而產生泄漏。
為此,在 Tomcat 中引入了 JreMemoryLeakPreventionListener 這個組件。實現思路是在 Tomcat 啟動時,通過 System class Loader 來加載這些類。 由于類加載器的加載原理(默認父優先,而且這些系統的類,都會委托給系統類加載器進行加載),這些類不會再被 WebclassLoader 重新加載,從而減小內存泄漏的產生。
默認在 Tomcat 的配置 server.xml 中已經開啟了該組件,所以這些功能你已經不知不覺中在使用。
以上就是Tomcat與內存泄露處理的示例分析,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。