記一次xstream引起的內存泄漏


一、起
支付系統突然出現頻繁的超時,查看error日志沒有什么發現,憑經驗去gc日志瞅一眼,有頻繁的full gc,而且每兩次gc,老年代會有80%的內存無法被回收,基本確認是系統出現內存泄漏,導致老年代空間被占滿,頻繁觸發full gc,full gc 觸發stop the word,導致業務接口超時。
 
二、承
2.1、dump內存數據
#netstat -tunlp|grep 端口號
#jmap -dump:live,file=dump.file pid
2.2、解析內存數據
#jhat -J-Xmx8192M dump.file
2.3、分析內存數據
查看實例個數前五的對象,可以看出第一名是第二名的實例個數的十幾倍,大概率是class com.thoughtworks.xstream.core.util.CompositeClassLoader 對象造成的內存泄漏。
晚上搜資料,果然是。
我們支付系統在和微信第三方支付系統進行交互處理支付業務時,需要解析微信接口返回的XML數據,用到了xstream,而且每個請求都會新建一個xstream對象,xstream對象內部又會new CompositeClassLoader對象,Class.forName調用該Application ClassLoader,gc時xstream會被回收,但是CompositeClassLoader對象會被其他對象引用,大致一直無法回收,如果支付系統運行時間久了,就會有大量無用但是無法被回收的CompositeClassLoader,導致內存泄漏頻繁gc。
 
 
 
 
 
這是一個比較典型的ClassLoader內存泄漏問題。
正規流程應該是:一個classloader就是一個從jar文件中加載.class文件的簡單的類。當你卸載應用時,該classloader連同所有由該classloader加載的類都將被垃圾回收掉(可能不會立即回收,但是沒用任何引用的對象,最終都會被gc回收)。
但現實情況是,有時候有些對象會防不勝防地引用到classloader,這樣gc就無法對其進行回收。導致內存泄漏。
 
三、轉
此問題的解決方案。
XStream官方有一段話:The XStream instance is thread-safe. That is, once the XStream instance has been created and configured, it may be shared across multiple threads allowing objects to be serialized/deserialized concurrently.即XStream是線程安全的,不需要重復初始化xstream對象,每一種類型實例化一個對象即可,而正是由於開發人員錯誤地在每次處理請求時都實例化一個新的xstream對象,沒有把相同類型的緩存起來使用,才導致了該性能問題。
落地到支付系統,則需要為每個反序列化的對象聲明一個靜態的XStream,重復利用,問題解決。
 
四、合
內存泄漏是每個Java程序猿必須要面對的問題,后期可以總結一下常見內存泄漏的場景。
 
http://note.youdao.com/noteshare?id=6e36d4003850b41166e8cfda085a825e
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM