一次由於八股文引起的記憶體洩漏
來源:阿里雲開發者
阿里妹導讀
一、第一次報錯系統監控現象
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記憶體
- js垃圾回收機制和引起記憶體洩漏的操作JS記憶體
- 記一次堆外記憶體洩漏分析記憶體
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- 記憶體洩漏的原因記憶體
- jvm 記憶體洩漏JVM記憶體
- Android 記憶體洩漏Android記憶體
- Java記憶體洩漏Java記憶體
- js記憶體洩漏JS記憶體
- Android記憶體洩漏Android記憶體
- 關於PHP記憶體洩漏的問題PHP記憶體
- 記一次使用 laravel-s 記憶體洩漏Laravel記憶體
- 記一次使用windbg排查記憶體洩漏的過程記憶體
- 記一次 Ruby 記憶體洩漏的排查和修復記憶體
- 關於記一次 Go 服務記憶體洩漏問題調查Go記憶體
- valgrind 記憶體洩漏分析記憶體
- 記憶體的分配與釋放,記憶體洩漏記憶體
- Spring Boot引起的“堆外記憶體洩漏”排查及經驗總結Spring Boot記憶體
- 記一次 Java 應用記憶體洩漏的定位過程Java記憶體
- 【記憶體洩漏和記憶體溢位】JavaScript之深入淺出理解記憶體洩漏和記憶體溢位記憶體溢位JavaScript
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- Android中常見的記憶體洩漏Android記憶體
- .NET 記憶體洩漏的爭議記憶體
- Swift的ARC和記憶體洩漏Swift記憶體
- vue使用中的記憶體洩漏Vue記憶體
- Android中的記憶體洩漏模式Android記憶體模式
- [譯] Swift 中的記憶體洩漏Swift記憶體
- 一次排查Java專案記憶體洩漏的過程Java記憶體
- 記憶體洩漏除錯工具記憶體除錯
- ThreadLocal真會記憶體洩漏?thread記憶體
- Perfdog 玩轉記憶體洩漏記憶體
- .Net程式記憶體洩漏解析記憶體
- iOS檢測記憶體洩漏iOS記憶體
- Android記憶體洩漏場景Android記憶體
- ThreadLocal記憶體洩漏問題thread記憶體
- PHP 記憶體洩漏分析定位PHP記憶體