1、起
支付系統忽然出現頻繁的超時,查看error日誌沒有什麼發現,憑經驗去gc日誌瞅一眼,有頻繁的full gc,並且每兩次gc,老年代會有80%的內存沒法被回收,基本確認是系統出現內存泄漏,致使老年代空間被佔滿,頻繁觸發full gc,full gc 觸發stop the word,致使業務接口超時。
2、承
2.一、dump內存數據
#netstat -tunlp|grep 端口號
#jmap -dump:live,file=dump.file pid
2.二、解析內存數據
#jhat -J-Xmx8192M dump.file
2.三、分析內存數據
查看實例個數前五的對象,能夠看出第一名是第二名的實例個數的十幾倍,大機率是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就沒法對其進行回收。致使內存泄漏。
3、轉
此問題的解決方案。
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,重複利用,問題解決。
4、合
內存泄漏是每一個Java程序猿必需要面對的問題,後期能夠總結一下常見內存泄漏的場景。
http://note.youdao.com/noteshare?id=6e36d4003850b41166e8cfda085a825e