java應用性能調優之詳解System的gc垃圾回收方法

1、什麼是System.gc()?

System.gc()是用Java,C#和許多其餘流行的高級編程語言提供的API。當它被調用時,它將盡最大努力從內存中清除垃圾(即未被引用的對象)。名詞解釋:GC,Garbage Collection,垃圾回收,下文會常用。java

2、誰能夠調用System.gc()?

 System.gc() 能夠從應用程序堆棧的各個部分調用:程序員

  • 您本身開發的應用程序能夠顯式的調用 System.gc() 方法。
  •  System.gc() 也能夠由您的第三方庫,框架觸發。
  • 能夠由外部工具(如VisualVM)經過使用JMX觸發
  • 若是您的應用程序使用了RMI,RMI會按期調用 System.gc() 。

3、調用System.gc()有什麼弊端?

當 System.gc() 或 Runtime.getRuntime().gc()API被調用時,將觸發完整的GC事件。在GC完成以前,整個JVM將凍結(即正在運行的全部服務將被暫停),一般完整的GC須要很長時間才能完成。所以在不合適的時間運行GC,將致使不良的用戶體驗,甚至是崩潰。 JVM具備複雜的算法,該算法始終在後臺運行,進行全部計算以及有關什麼時候觸發GC的計算。當您顯式調用System.gc()調用時,全部這些計算都將被拋掉。算法

4、哪些場景適合顯式調用System.gc()?

GC操做應該由JVM自行控制,在絕大部分的場景都不建議程序員手動寫代碼顯式進行System.gc()操做,可是也不排除其中個別例外:在咱們開發多個微服務時,每一個服務都有多個備份節點。在非業務高峯時段,咱們能夠從微服務-負載均衡的節點池中取出其中一個JVM實例。而後經過該JVM上的JMX顯式觸發System.gc()調用,一旦GC事件完成而且從內存中清除了垃圾,將該JVM放回到微服務-負載均衡的節點池中。 固然這個過程須要很好的微服務管理及服務發佈機制配合,這樣既能保證JVM垃圾內存的有效清理,又不影響業務的正常運行。spring

5、如何檢測您的應用程序正在進行System.gc()?

如第二小節所講: System.gc() 能夠從多個渠道進行的調用,而不只僅是從您的應用程序源代碼進行的調用。所以,搜索您的應用程序代碼System.gc() 字符串,不足以知道 GC是否正在被調用。這就構成了一個挑戰:如何檢測應用程序是否正在進行垃圾回收?這就是GC日誌派上用場的地方。編程

// java 8 啓用GC日誌:
// -XX:+PrintGCDetails -Xloggc:<gc-log-file-path> ,例以下面這行代碼
-XX:+PrintGCDetails -Xloggc:/opt/tmp/myapp-gc.log

// java 9 啓用GC日誌:-Xlog:gc*:file=<gc-log-file-path> ,例以下面這行代碼
-Xlog:gc*:file=/opt/tmp/myapp-gc.log

建議始終在全部生產服務器中始終啓用GC日誌,由於它有助於您排除故障並優化應用程序性能。啓用GC日誌只會增長微不足道的開銷。還能夠將您的GC日誌上傳到垃圾收集日誌分析器工具,例如GCeasy,HP JMeter等。這些工具將生成豐富的垃圾收集分析報告。springboot

GCeasy.io工具報告的GC緣由

上圖摘自GCeasy生成的報告。性能優化

6、如何禁止GC顯式調用或調整調用GC的頻率?

若是咱們就是想避免程序員顯式調用GC,避免不成熟的程序員在不合適時間調用GC,避免人爲形成的GC崩潰,該怎麼辦?能夠經過以下方法:服務器

搜索和替換

在代碼庫中搜索 System.gc() 和Runtime.getRuntime().gc()。若是看到匹配項,則將其刪除。可是這種方法沒法避免第三方庫、框架或經過外部源進行調用,那麼參考第二種方法。app

經過JVM參數強制禁止

經過傳遞JVM參數  -XX:+DisableExplicitGC來強制禁止顯式調用。這種方式強制、有效,應用程序內的任何GC顯式代碼調用System.gc() 都將被禁止生效。JVM自身的GC策略不受此參數影響,只禁止人爲的觸發GC。負載均衡

RMI

若是您的應用程序正在使用RMI,則能夠控制GC調用的頻率 。啓動應用程序時,可使用如下JVM參數配置該頻率:

  •  -Dsun.rmi.dgc.server.gcInterval=n
  •  -Dsun.rmi.dgc.client.gcInterval=n

這些屬性的默認值在

  • JDK 1.4.2和5.0是60000毫秒(即60秒)
  • JDK 6和更高版本是3600000毫秒(即60分鐘)

若是您的應用主機內存資源很是富餘,您能夠將這些屬性設置爲很高的值,以即可以將GC帶來的對應用程序的影響最小化。這也是應用程序性能優化的一種方式之一。

期待您的關注

相關文章
相關標籤/搜索