有一個應用平臺是基於eclipse rcp技術開發的。此平臺支持應用邏輯類動態加載。此平臺採用的自定義類加載器來加載具體應用業務邏輯處理類。平臺定時掃描已經加載過的類是否改變過。如果有類的已經改變了則創建新的類加載器,平臺通過新的類加載器加載應用邏輯處理類。
有一天,使用MAT工具分析java的heapdump。發現有很多自定義類加載器存在。而且出現多份同名應用業務邏輯處理類的Class。
這明顯存在內存泄露的問題。
通過MAT工具的多種功能反覆研究,終於找到了一個意料不到內存泄露原因。元兇竟然是eclipse內部AdapterManager。AdapterManager緩存了應用業務邏輯處理類的Class對象。
AdapterManager爲什麼會緩存應用業務處理邏輯類呢?
此平臺定義一個應用業務邏輯處理類的抽象父類。此父類實現了接口org.eclipse.core.runtime.IAdaptable。此接口只有一個方法:
此抽象父類實現IAdaptable的方法如下:
這樣處理可以給具體應用業務處理邏輯類調用平臺的公共服務接口帶來方便。調用者不需要知道接口的實現類是誰,此接口的實現是在哪裏。
調用者只需要類似如下調用就可使用一些公共服務:
- IHttpCommunication httpComm=(IHttpCommunication)this.getAdapter(IHttpCommunication.class);
- IPrintService printService=(IPrintService)this.getAdapter(IPrintService.class);
AdapterManager爲什麼要緩存一些Class呢?
AdapterManager的loadAapter會調用一個方法:
緩存的目的就是爲了方便查找IAdapterFactory。
找到了問題的根源,解決辦法就呼之欲出了。在創建新的自定義類加載器時,主動調用AdapterManager的flushLookup就可以了。