2010-06-02 24 views
10

在我參與的幾乎所有較大的Java項目中,我都注意到應用程序的服務質量隨着容器的正常運行時間而下降。這很可能是由於代碼中的內存泄漏。處理大型Java項目中的內存泄漏的最佳實踐?

解決此問題的正確方法顯然是追溯問題的根本原因並修復代碼中的泄漏。解決這個問題的方法很簡單,就是重啓Tomcat(或者你正在使用的任何一個servlet容器)。

這是我的三個問題:

  • 假設你選擇通過跟蹤問題(內存泄漏)的根本原因,解決問題,你會如何收集數據以放大的問題?

  • 假設您選擇通過簡單地重新啓動容器來加快速度的快速和骯髒的方式,您將如何收集數據以選擇最佳的重新啓動週期?

  • 您是否能夠長時間部署和運行項目,而無需重新啓動servlet容器以重獲生機?或者偶爾的servlet重新啓動一個人必須接受的東西?

回答

9

假設您選擇通過追蹤問題的根本原因(內存泄漏)來解決問題,您將如何收集數據以放大問題?

使用jmap進行堆轉儲並使用Eclipse Memory Analyzer加載轉儲。從那裏你可以分析哪些對象吃掉了最多的內存,哪些「根源」阻止了其他對象被收集等。

還有其他的堆分析程序,如jhat,但我發現EMA成爲最快和最好的(免費)解決方案。

假設您選擇通過簡單地重新啓動容器來加快速度的快速和骯髒的方法,您將如何收集數據以選擇最佳的重新啓動週期?

使用JMX監視堆大小和其他堆和GC統計信息。

您是否能夠長時間部署和運行項目,而無需重新啓動servlet容器以重獲生機?

是的。通過避免/修復內存泄漏。

+1

+1爲簡單,沒有廢話的答案。重新啓動容器是一個簡單的解決方法,但不是一個長期的解決方案。自動執行容器重啓是一種自動化的解決方法,它具有解決方案的一些優點,但也有很多缺點。 – 2010-06-02 18:47:47

1

理想情況下,您不應該重新啓動程序或servlet。

我的經驗是,大部分內存問題的原因通常是由於分配或合併一小組類的問題導致的。

像VisualVM這樣的工具非常適合您,因爲您可以找出對象分配的主要位置。

這對tomcat來說可能有點棘手,因爲你也會監視框架,但是通過足夠的細心和耐心,你可以經常識別邏輯中的熱點。

2

這裏有一些很棒的分析工具。學會定期使用一個並瞭解內存分配輸出。

基本上你按照這個過程在程序的每一個重要的功能:

  • 整個過程運行一次
  • GC兩次
  • 標記您的當前分配計數的所有對象
  • 運行通過你的再次處理
  • GC兩次
  • 再次標記
  • 這兩個標記的差異

如果它們不是非常接近,那麼您可能有泄漏。

如果在此過程的每次迭代中有任何對象數增長了給定量,那麼您絕對有泄漏。