您需要了解的所有有关System.gc()的信息
在本文中,我們試圖回答有關System.gc()API調用的最常見問題。 我們希望它會有所幫助。
什么是System.gc()?
System.gc()是用Java,Android,C#和其他流行語言提供的API。 當被調用時,它將盡最大努力從內存中清除累積的未引用對象(即垃圾)。
誰調用System.gc()?
可以從應用程序堆棧的各個部分調用System.gc()調用:
- 您自己的應用程序開發人員可能正在顯式調用System.gc()方法。
- 有時System.gc()可以由您的第三方庫,框架甚至有時由應用程序服務器觸發。
- 可以通過使用JMX從外部工具(如VisualVM)觸發
- 如果您的應用程序正在使用RMI,則RMI會定期調用System.gc()。
調用System.gc()有什么弊端?
當從您的應用程序調用System.gc()或Runtime.getRuntime()。gc()API調用時,世界各地的Full GC事件將被觸發。 在世界各地的完整GC期間,整個JVM將凍結(即,正在運行的所有客戶交易將被暫停)。 通常,這些完整GC需要很長時間才能完成。 因此,在不需要運行GC的不必要時間,它有可能導致不良的用戶體驗和SLA。
JVM具有復雜的算法,該算法始終在后臺運行,進行所有計算以及有關何時觸發GC的計算。 當您調用System.gc()調用時,所有這些計算都將被拋掉。 如果JVM僅在一毫秒后觸發了GC事件,然后又從應用程序中再次調用System.gc(),該怎么辦? 因為從您的應用程序中您不知道GC何時運行。
是否有任何良好/有效的理由來調用System.gc()?
從應用程序調用System.gc()的原因很多,我們還沒有遇到。 但是,這是我們在一家大型航空公司的應用程序中看到的有趣的用例。 該應用程序使用1 TB的內存。 此應用程序的完整GC暫停時間大約需要5分鐘才能完成。 是的,不要感到震驚,這是5分鐘🙂(但我們也看到了23分鐘的GC暫停時間的情況)。 為了避免由于此暫停時間而對客戶造成的影響,該航空公司已實施了明智的解決方案。 每天晚上,他們一次從負載均衡器池中取出一個JVM實例。 然后,它們通過該JVM上的JMX顯式觸發System.gc()調用。 一旦GC事件完成并且從內存中清除了垃圾,他們就會將該JVM放回到負載平衡器池中。 通過這種巧妙的解決方案,他們將這5分鐘的GC暫停時間對客戶的影響降至最低。
如何檢測是否從您的應用程序進行了System.gc()調用?
如您在“誰調用System.gc()?”中所注意到的那樣。 部分,您可以看到System.gc()調用將從多個源進行,而不僅僅是從您的應用程序源代碼進行。 因此,僅搜索應用程序代碼'System.gc()'字符串不足以判斷您的應用程序是否在進行System.gc()調用。 因此,這構成了一個挑戰:如何檢測是否在整個應用程序堆棧中調用了System.gc()調用?
這是GC日志很方便的地方。 在應用程序中啟用GC日志 。 實際上,建議始終在所有生產服務器中始終啟用GC日志,因為它有助于您排除故障并優化應用程序性能。 啟用GC日志會增加微不足道的開銷(如果可以觀察到的話)。 現在,將您的GC日志上傳到垃圾收集日志分析器工具。
上圖摘自GCeasy生成的報告的“ GC Causes”部分。 您可以看到“ System.gc()”調用被調用304次,占GC暫停時間的52.42%。
如何刪除System.gc()調用?
您可以通過以下解決方案刪除顯式的System.gc()調用:
一個。 搜索和替換
這可能是一種傳統方法:-),但是可以。 在應用程序代碼庫中搜索“ System.gc()”和“ Runtime.getRuntime()。gc()”。 如果看到匹配項,則將其刪除。 如果從您的應用程序源代碼中調用“ System.gc()”,則此解決方案將起作用。 如果“ System.gc()”要從您的第三方庫,框架或通過外部源進行調用,則此解決方案將不起作用。 在這種情況下,您可以考慮使用#b中概述的選項。
b。 -XX:+ DisableExplicitGC
啟動應用程序時,可以通過傳遞JVM參數'-XX:+ DisableExplicitGC'來強制禁用System.gc()調用。 此選項將使在應用程序堆棧中任何位置調用的所有“ System.gc()”調用靜音。
C。 RMI
如果您的應用程序使用RMI,則可以控制“ System.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分鐘)
您可能需要將這些屬性設置為很高的值,以便可以將影響最小化。
翻譯自: https://www.javacodegeeks.com/2019/09/all-you-need-to-know-about-system-gc.html
總結
以上是生活随笔為你收集整理的您需要了解的所有有关System.gc()的信息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科沃斯设置(科沃斯设置吸力)
- 下一篇: jdk8 接口抽象类区别_JDK 8时代