6

我正在使用AppDynamics监控一个生产系统,我们只是让系统缓慢爬行并且几乎冻结。就在此事件之前,AppDynamics 将所有 GC 活动(次要和主要类似)平线显示几分钟......然后恢复活力。

即使在系统超低负载期间,我们仍然会看到我们的 JVM 执行一些GC 活动。我们从来没有让它完全平坦并下降到 0。

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

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

4

3 回答 3

1

您的操作系统是否启用了交换。

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

我的理论是这样的:

  • 操作系统内存快满了。
  • 操作系统从 Java 请求内存。
  • 这会触发 Java 进入完整的 GC 以尝试释放内存。
  • 完整的 GC 几乎会触及虚拟机内存的每一块,甚至是已换出的项目。
  • 系统尝试将数据交换回 VM 的内存(在已经用完 ram 的系统上)
  • 这一直在滚雪球。

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

多个大型 VM 会使情况变得更糟,我运行 3 或 4 个大型 VM,当我的 RAM 使用率超过 60-70% 时,我的系统现在开始占用。

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

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

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

于 2013-04-19T16:00:01.117 回答
1

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

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

操作系统可以阻止 JVM 吗?
是的,它 perflecty 可以而且做得很多,但速度比你想象的要快,所有进程都在同一时间运行。
jvm 是一个和他一样的进程,在操作系统的控制下。您必须检查应用程序挂起时使用的 cpu(在不在 jvm 中的服务器上进行监视)。如果它非常低,那么我会看到 2 个原因(但还有更多):

  • 您的服务器没有足够的 RAM 并且正在交换(RAM <-> 磁盘),进程变得非常缓慢。在这种情况下,服务器上的 cpu 会很高,但 jvm 上的 cpu 会很低
  • 另一个进程或服务器获取资源,而您的应用程序或服务器什么也没收到。检查 CentO 上的优先级。
于 2013-04-19T15:49:57.447 回答
0

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

在大多数 Java 虚拟机中,应用程序线程并不是唯一运行的线程。除了应用程序线程之外,还有编译线程、终结器线程、垃圾收集线程等等。将 CPU 内核分配给这些线程和机器上运行的其他程序的其他线程的调度决策基于许多参数(线程优先级、它们的最后执行时间等),这些参数尽量对所有线程公平。因此,实际上,系统中的任何线程都不应该等待 CPU 分配的时间过长,操作系统也不应该无限期地阻塞任何线程。

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

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

当然每个垃圾收集器的细节因JVM而异。为了在伤害上加点盐,一些 JVM 支持不止一种类型的垃圾收集器。但是在空闲应用程序中看到最小的垃圾收集活动并不奇怪。

于 2013-04-19T15:59:28.653 回答