OS可以阻止Java进程进行垃圾回收吗?

时间:2013-04-18 18:40:58

标签: java garbage-collection jvm heap appdynamics

我正在使用AppDynamics监控生产系统,我们只是让系统慢慢爬行并且几乎冻结。就在此事件发生之前,AppDynamics将所有GC活动(次要和主要类似)展示几分钟......然后再回归生活。

即使在系统负载过低的情况下,我们仍然会看到我们的JVM正在进行某些 GC活动。我们从来没有完全扁平化并且降至0。

此外 - 网络I / O在与GC /内存扁平线相同的时间实现扁平化。

所以我问:系统级别的东西会导致JVM冻结,还是导致垃圾收集挂起/冻结?这是在CentOS机器上。

3 个答案:

答案 0 :(得分:1)

如果没有更多信息,很难找到问题的确切原因。

但我可以尝试回答你的问题:
OS可以阻止垃圾收集吗?
它不太可能比您的操作系统阻塞线程垃圾收集器并让其他线程运行。你不应该这样调查。

OS可以阻止JVM吗?
是的,它可以并且它可以做很多事情,但是比你认为过程全部同时运行的速度要快得多。
jvm是一个像他人一样的过程,他在操作系统的控制之下。您必须检查应用程序挂起时使用的CPU(监视服务器上的监视不在jvm中)。如果它非常低,那么我看到2个原因(但还有更多):

  • 您的服务器没有足够的RAM并且正在交换(RAM< - >磁盘),进程变得非常慢。在这种情况下,cpu在服务器上会很高,但对于jvm来说很低
  • 另一个进程或服务器抓取资源,您的应用程序或服务器不会收到任何内容。检查CentOs的优先级。

答案 1 :(得分:0)

理论上,是的,它可以。但它实践,它永远不应该。

在大多数Java虚拟机中,应用程序线程不是唯一正在运行的线程。除了应用程序线程,还有编译线程,终结器线程,垃圾收集线程等等。用于将CPU核心分配给这些线程以及来自机器上运行的其他程序的其他线程的调度决策基于许多参数(线程优先级,它们的上次执行时间等),这些参数对所有线程都是公平的。因此,在实践中,系统中的任何线程都不应该在不合理的长时间内等待CPU分配,并且操作系统不应该无限制地阻塞任何线程。

垃圾收集线程(和其他VM线程)需要执行的活动很少。他们需要定期检查是否需要垃圾收集。即使应用程序线程全部被挂起,也可能有其他VM线程,例如JIT编译器线程或终结器线程,它们可以工作,因此可以分配对象并触发垃圾回收。对于在Java中而不是在C / C ++中实现VM线程的元循环JVM尤其如此;

此外,大多数现代JVM使用分代垃圾收集器(垃圾收集器将堆分成不同的空间并将不同年龄的对象放在堆的不同部分)这意味着随着对象变得越来越老,它们需要是搬到了其他较旧的地方。因此,即使不需要收集对象,分代垃圾收集器也可以将对象从一个空间移动到另一个空间。

当然每个垃圾收集器的细节都不同于JVM到JVM。为了对伤害施加更多的盐,一些JVM支持多种类型的垃圾收集器。但是在空闲应用程序中查看最小的垃圾收集活动并不令人意外。

答案 2 :(得分:0)

您的操作系统是否已启用交换功能。

我注意到,一旦它在启用了交换的操作系统上填满了所有内存,它就会发现Java的巨大问题 - 它实际上会破坏Windows系统,有效地锁定它们并导致重新启动。

我的理论是:

  • OS ram接近满员。
  • 操作系统从Java请求内存。
  • 这会将Java触发到一个完整的GC以尝试释放内存。
  • 完整的GC几乎触及了每个虚拟机内存,甚至是已换掉的项目。
  • 系统尝试将数据交换回VM的内存(在已经停止运行的系统上)
  • 这一直在滚雪球。

起初它不会对系统产生太大影响,但是如果你尝试启动一个需要大量内存的应用程序,它可能需要很长时间,而且你的系统只会不断降级。

多个大型虚拟机可能会使情况变得更糟,我运行了3个或4个巨大的虚拟机,当我的RAM使用率超过60-70%时,我的系统现在开始出现。

这是猜想,但它描述了我经过几天测试后看到的行为。

效果是所有交换似乎都是“预防”gc。更准确地说,操作系统花费了大部分GC时间交换,这使得它看起来像是在GC期间无所事事。

修复 - 将-Xmx设置为较低的值,将其放下,直到您留出足够的空间以避免交换。这总是解决了我的问题,如果它不能解决你的问题,那么我对你的问题的原因是错的:)