【问题标题】:Tuning Garbage Collection parameters in Java在 Java 中调整垃圾收集参数
【发布时间】:2011-08-24 18:05:23
【问题描述】:

我有一个服务器 java 组件,它在启动时有巨大的内存需求,并且逐渐降低。因此,作为启动时的示例,内存需求可能会达到 4g;在最初的激增结束后将下降到 2g。我已将组件配置为以5g内存启动,组件启动良好;使用的内存激增到 4g,然后下降到接近 2g。此时堆消耗的内存仍然徘徊在 4g 左右,我想降低它(基本上将可用内存保持在几百 mb 而不是 2g。我尝试使用 MinFreeHeapRatio 和 MaxFreeHeapRatio 将它们从默认值降低但这导致在初始峰值期间初始运行后没有触发垃圾收集,并且使用的内存保持在高于正常水平。任何指针都会有很大帮助。

【问题讨论】:

标签: java garbage-collection


【解决方案1】:

首先,我问您为什么担心释放服务器上的 2 GB 内存? 2GB 的内存大约是 100 美元或更少。如果这是在桌面上,我想我可以理解这种担心。

如果您确实有充分的理由考虑它,这可能与您使用的垃圾收集算法有关。有些算法会将未使用的内存释放回操作系统,有些则不会。 http://www.stefankrause.net/wp/?p=14 有一些图表等与此相关。您可能想尝试 G1 收集器,因为它似乎很容易将内存释放回操作系统。

从 cmets 编辑 如果他们都选择一次最大负荷怎么办?您是否同意其中一些将内存分页到磁盘并减慢服务器速度?我将在具有足够内存的服务器上运行它们,以在最大堆上运行所有应用程序,另外还有 4-6GB 用于操作系统/缓存。 32 或 64 GB 的服务器很常见,您可以获得更多。

【讨论】:

  • 我有几个这样的组件在提供各种服务的服务器上运行,所以 2g 分布在多个组件上会导致相当多的未利用资源。
  • 你是对的;但是,正如我所说,峰值仅在启动时发生,服务器将有足够的内存来承担整个负载;但是应该有一种方法来配置组件,一旦初始峰值结束,它们就会放弃内存。
  • 您是否按照我的建议尝试使用 G1?
  • 您可以花 2.5 万英镑购买 64 GB 的服务器,花 3.5 万英镑购买 96 GB 的服务器
  • @Peter 令人惊讶的是,尤其是在虚拟机领域,内存和磁盘空间现在再次成为稀缺商品。而且“Xen Masters”越来越吝啬,因为刀片并不便宜,特别是如果你没有更多的插槽给他们。当人们将它们视为廉价资源时,这些廉价资源的成本是惊人的。而且我敢肯定 Scorpion 会很乐意用你价值 3500 英镑的服务器来解决他的问题,因为你似乎只是在分发它们。
【解决方案2】:

您必须记住,JVM 在启动时保留虚拟内存,并且永远不会将其归还给操作系统(直到程序退出)您最多可以希望将未使用的内存换出(这不是一个好计划)如果您不希望应用程序使用超过一定数量的内存,则必须将其限制为该数量。

如果您有许多组件使用内存高峰,您应该考虑重写它们以在启动时使用更少的内存或在同一个 JVM 中使用多个组件,这样额外的内存就不那么重要了。

【讨论】:

  • 除非 Java 7 的文档实际上说它会向操作系统释放内存,否则我不会相信它会这样做。堆大小只是表示分配给堆的内存量,而不是应用程序总共使用的内存量。
  • 解释链接页面上的图表为什么会下降。您可以在本地重现测试......
  • 堆只是应用程序使用的总内存的一部分。仅仅因为它没有被堆使用并不意味着内存已经返回给操作系统。您需要查看操作系统的可用内存。
  • 不释放内存给操作系统应该是一个错误;看到这个bugs.sun.com/bugdatabase/view_bug.do?bug_id=4065018。这是在 jdk 的初始版本中提出的。
  • 这是 Azul 的 JVM 的主要卖点之一。他们声称他们必须在虚拟机中使用自定义内核,因为 Windows 和 Linux 没有将内存释放回操作系统所需的支持。即它不仅仅是一个错误,也不能轻易修复。 AFAIK Linux 上没有 C 程序将内存释放回操作系统(尽管某些 Windows 程序会这样做)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
相关资源
最近更新 更多