一次由於八股文引起的記憶體洩漏
來源:阿里雲開發者
阿里妹導讀
一、第一次報錯系統監控現象
14:16 機器釋出新程式碼 15:35 機器開始出現fullGC 15:50 機器fullGC耗時上升 17:48 對JVM進行dump操作,然後進行機器置換
1.有大量阻塞執行緒
1.1 排查過程
分析執行緒Dump檔案
1.2 分析原因
@Componentpublic class OssClient implements BeanPostProcessor {private OSS ossClient = null;/** * 初始化OSS客戶端 **/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 省略程式碼……// 以下是阻塞程式碼行 ossClient = new OSSClientBuilder().build(ossProperty.getString("endpoint"), ossProperty.getString("accessKeyId"), ossProperty.getString("accessKeySecret"), configuration);// 省略程式碼……return bean; }}
1.3 第一次問題解決
二、第二次報錯系統監控現象
19:48 機器釋出新程式碼 22:30 機器開始出現fullGC 23:30 機器fullGC耗時上升 00:30 對JVM進行dump操作,然後進行機器置換
2.1 排查過程
分析執行緒Dump檔案
1.阻塞執行緒確實是由於OSS跨單元拒絕訪問導致的
分析GC Dump檔案
這裡顯示有11萬個org.apache.http.impl.conn.PoolingHttpClientConnectionManager例項,佔用了80.42%的堆記憶體,但是這個類並不是我直接引入的,那麼一定是有間接依賴,生成了大量該類物件。
另外,透過類名,能判斷這個物件是和網路請求有關係,而我這個應用上需要網路請求的地方有幾處: 1.訪問DB 2.訪問Redis 3.訪問OSS 4.進行HSF呼叫
2.2 分析原因
@Componentpublic class OssClient implements BeanPostProcessor {private OSS ossClient = null;/** * 初始化OSS客戶端 **/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 省略程式碼……// 一下是阻塞程式碼行 ossClient = new OSSClientBuilder().build(ossProperty.getString("endpoint"), ossProperty.getString("accessKeyId"), ossProperty.getString("accessKeySecret"), configuration);// 省略程式碼……return bean; }}
排查原因過程中,有一篇文章給了我答案,下面是這篇文章給的OOM原因的解釋:
每次new OSSClient的時候,都會往List中放入HttpClientConnectionManager,但是沒有主動呼叫OSSClient的shutdown的方法,所以List只會增大不會變小。反觀我們的程式碼,每次介面呼叫都會建立一個OSSClient物件,但卻在使用完之後,沒有呼叫OSSClient的shutdown方法,導致未呼叫IdleConnectionReaper的removeConnectionManager方法,使得IdleConnectionReaper中靜態列表儲存的PoolingHttpClientConnectionManager例項資料一直會增長,一直都不會被回收,最終帶來的結果就是OOM。
2.3 最終問題解決
public class OssClient implements InitializingBean {
private OSS ossClient = null;
/**
* 初始化OSS客戶端
**/
public void afterPropertiesSet() throws Exception {
// 省略程式碼……
// 以下是阻塞程式碼行
ossClient = new OSSClientBuilder().build(ossProperty.getString("endpoint"),
ossProperty.getString("accessKeyId"),
ossProperty.getString("accessKeySecret"),
configuration);
// 省略程式碼……
}
}
總結
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70024923/viewspace-3006592/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- WebView引起的記憶體洩漏WebView記憶體
- 一次 Java 記憶體洩漏的排查Java記憶體
- 記憶體洩漏引起的 資料庫效能問題記憶體資料庫
- 記憶體洩漏記憶體
- 關於java中的記憶體洩漏Java記憶體
- js垃圾回收機制和引起記憶體洩漏的操作JS記憶體
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- 記憶體洩漏的原因記憶體
- js記憶體洩漏JS記憶體
- Java記憶體洩漏Java記憶體
- webView 記憶體洩漏WebView記憶體
- Javascript記憶體洩漏JavaScript記憶體
- 記一次使用 laravel-s 記憶體洩漏Laravel記憶體
- handlder引起的記憶體洩漏問題以及解決辦法記憶體
- 關於PHP記憶體洩漏的問題PHP記憶體
- 記一次使用windbg排查記憶體洩漏的過程記憶體
- 記一次 Ruby 記憶體洩漏的排查和修復記憶體
- ARC下的記憶體洩漏記憶體
- 【轉】Java的記憶體洩漏Java記憶體
- 記憶體分析與記憶體洩漏定位記憶體
- 記憶體洩漏和記憶體溢位記憶體溢位
- 關於記一次 Go 服務記憶體洩漏問題調查Go記憶體
- valgrind 記憶體洩漏分析記憶體
- Android 記憶體洩漏Android記憶體
- Android記憶體洩漏Android記憶體
- 淺談記憶體洩漏記憶體
- JavaScript 記憶體洩漏教程JavaScript記憶體
- 說說 記憶體洩漏記憶體
- 記憶體的分配與釋放,記憶體洩漏記憶體
- 記一次 Java 應用記憶體洩漏的定位過程Java記憶體
- 記憶體洩露引起的問題記憶體洩露
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- 一次排查Java專案記憶體洩漏的過程Java記憶體
- Swift的ARC和記憶體洩漏Swift記憶體
- .NET 記憶體洩漏的爭議記憶體
- vue使用中的記憶體洩漏Vue記憶體
- [譯] Swift 中的記憶體洩漏Swift記憶體
- Android中的記憶體洩漏Android記憶體