java - 解释在 JBoss 服务器上观察到的 JVM 垃圾收集

标签 java jboss garbage-collection jvm performance

使用 VisualVM,我观察到 JBoss 服务器上的以下堆使用情况:

VisualVm Screenshot of Heap usage

服务器使用以下(相关的)JVM 选项启动:

-Xrs -Xms3072m -Xmx3072m -XX:MaxPermSize=512m -XX:+UseParallelOldGC -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000

而且我们目前还启用了 GC 日志记录:

-XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:log\gc.log

基本上我对观察到的模式很满意,因为看起来我们没有任何内存泄漏(该模式会在几天内重复出现)。

不过我想知道有没有优化的空间?

首先,我不明白为什么当堆使用量达到大约 2GB 时垃圾收集就已经开始了?在我看来它可以稍后启动,因为堆将有 3GB 可用?

此外,我会对有关观察到的堆使用模式和使用的 JVM 选项的提示感兴趣:

  • 观察到的模式是否允许我得出关于使用的 GC 策略 (UseParallelOldGC) 的结论?考虑到观察到的堆使用情况,这种策略是正确的吗?还是我应该尝试使用另一种策略?

  • 我能否优化 GC 过程,以便使用整个堆大小 (3GB)?

  • 现在似乎从未使用过完整的 3GB,我应该将 Xms/Xmx 减少到 2.5GB 吗?

  • 是否有任何明显的 GC 优化是我遗漏的?喜欢调整 -XX:NewSize 或 -XX:NewRatio?

  • 还有其他想到的提示吗?

谢谢!

最佳答案

我会说您的屏幕截图中的 GC 行为看起来“正常”。

根据许多情况,您通常希望在堆空间变得太满之前触发主要收集,否则很容易遇到 OutOfMemoryError。

此外,您是否知道 Java 的堆空间分为新的(eden)、当前的(survivor)和旧的(tenured)对象的不同区域?

这个答案提供了关于这个主题的一些很好的信息,所以我不会在这里重复:

How is the java memory pool divided?

基本上,堆的每个区域都会触发自己的收集。伊甸园空间通常会被频繁且“快速”地收集,幸存者和永久空间通常更大并且需要更长的时间来收集。

您能否根据上图减小堆大小?

是的。但是,您当前的配置允许您的应用程序有一些喘息的空间,如果它可能遇到更繁忙的时期或负载峰值的话。

你能优化 GC 吗?

是的,但是没有魔法设置。第一个问题是你真的需要吗?如果您的应用程序只是一个非交互式“处理器”,我真的不会打扰。如果您确实需要低暂停应用程序,则可以进行一些调整。权衡通常是您需要更多资源才能获得相同的结果。

我的经验是,当负载增加时,低暂停 JVM 配置有一个非常明显的下降点。如果您的应用程序通常相当空闲,但您希望在调用它时有“快速”响应,则低暂停可能是合适的。在繁忙的系统中,流量/负载达到峰值,您可能更喜欢更传统的方法。

总结

在任何情况下,都不要试图进行任意更改以“改进”您的配置。您的方法要科学和专业。

如果您没有可用的生产指标,请考虑使用 Apache JMeter 等工具构建负载测试场景以模拟应用程序的典型实时负载、增加的负载(例如 10%、20% 或 50% 等)和间歇性峰值负载。

对 GC 和应用程序都使用指标,至少衡量:

  • 平均吞吐量。
  • 峰值吞吐量。
  • 平均负载(CPU 和内存)。
  • 高峰负荷。
  • 应用程序暂停时间(总暂停时间和个别暂停时间)。
  • 执行收集所花费的时间。
  • 可靠性(OOME 等)。

一旦您对使用当前配置记录了应用程序性能的准确基准感到满意,您才应该开始进行任何更改。

显然,记录您的配置及其指标。记录任何更改,然后执行相同的基准测试。然后,您将能够看到任何性能增益(或损失)和任何可能适用的权衡。

以下是 Oracle 关于该主题的一些进一步阅读,以帮助您入门:

Java SE 6 Virtual Machine Garbage Collection Tuning

关于java - 解释在 JBoss 服务器上观察到的 JVM 垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12796162/

相关文章:

java - 充气城堡 : PEMReader => PEMParser

java - 使用 Java Checker Framework 的 Nullness Checker 注释可重入性

java - Apache Camel onException 和 deadLetterChannel 问题

jakarta-ee - keycloak - 如何获取当前用户密码或存储加密数据?

java - 我的 JAVA_OPTS 设置没问题吗?

java - 我们如何将与java中的对象关联的所有引用设置为null?

java - 为 Android 创建 "closed"可共享项目

java - HornetQ 队列事务超时

java - 非法访问(Quartz 与 JBoss)

没有引用对象时的 Java 垃圾回收