您需要了解的所有有关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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值