【问题标题】:Java decrease memory usageJava减少内存使用
【发布时间】:2012-02-03 10:52:43
【问题描述】:

我发现如果我的应用程序有很多可用内存,它会使用比它需要的更多的内存。我听说这种行为在所有 Java 应用程序中都很常见,但我无法接受。

所以问题是如何强制 Java 使用更少的内存?

我知道我可以每隔几秒手动调用System.gc(),但是这样做可以吗?还有其他方法吗?

P.S. 我的应用程序会在生产服务器上定期更新,我需要监控内存使用情况是否有一些泄漏等(通常没有泄漏,但如果出现泄漏,我应该尽快看到它),而且我还需要预测应该升级硬件的时间。如果 jvm 不可预测地改变了它的内存饥饿,所有这些事情都很难做到。所以我唯一想要的是强制 jvm 在内存使用方面是可预测的(如果用户数量翻倍,内存也应该翻倍)

【问题讨论】:

  • 也许是时候重新考虑一下为什么它是不可接受的了。你能给出一个技术上的理由吗,或者是什么让你不舒服?
  • 也许您不应该在生产服务器上进行测试?并且仅在您知道没有泄漏时才部署?
  • 这不是测试,当然我也有测试服务器,但是运行负载不同
  • 听起来您需要对应用程序进行内存分析,以便了解内存的使用情况。查看您为应用程序提供的最大内存不是很有用。一个更好的数字是 GC 之后使用了多少内存。鉴于内存成本非常低,我建议您获得比您可能需要的更多的内存,并且您不必在以后监视它或升级服务器(全面省钱)
  • 32 GB:8 x 4 GB 内存 1600 成本约为 160 美元。如果您从这么多内存开始,您可能不需要对其进行监控,这样可以在系统的整个生命周期内轻松节省这么多内存。

标签: java memory jvm


【解决方案1】:

您可以通过使用-Xmx 参数调用java 来告诉它使用更少的内存,即:

java -Xmx128M xxx

将以最大 128Mb 运行(by default in Java 6 这设置为“小于物理内存的 1/4 或 1GB”

不要一直打电话给System.gc()...你会浪费时间的;-)

另外,你为什么要担心这个?当java接近它允许的最大内存时,它无论如何都会进行GC扫描

【讨论】:

  • 不,我不能限制我的应用程序在内存中,因为几周后它可能会停止工作(它是一个服务器端应用程序并且用户数量在增长,所以我需要尽可能多的内存服务器可以提供)
  • 那就别担心了……它会崩溃吗?如果是这样,则可能是您的内存泄漏,并且没有任何System.gc() 可以解决此问题...
【解决方案2】:

我发现如果我的应用程序有很多可用内存,它使用的内存比它需要的多。我听说这种行为在所有 Java 应用程序中都很常见,但我无法接受。

这取决于您的意思是“比它需要更多的内存”。如果您的意思是,超过表示应用程序对象的最小内存,那么您是正确的。

Java 使用的内存比理论上可以避免的最低限度更多是标准行为。 “更糟糕的是”,大多数 JVM 不会将内存归还给操作系统……即使该内存已被 GC 释放。这两个属性对于通用垃圾收集器的高效运行都是必要的

如果这对您来说是不可接受的,那么您不应该使用垃圾收集语言。使用 C 或 C++。 (但也要注意,C / C++ 内存分配器能够将内存还给操作系统是不寻常的......即使实现允许它也是如此。)


积极的一面是,如果你给它足够的内存,Java(实际上是任何经过 GC 处理的语言)实际上会运行得更好。随着垃圾与非垃圾的比例增加,现代 GC 的工作效率更高,而更大的堆使这种情况发生。 (当然,您可能会走得太远,尤其是当应用程序正在与其他事物竞争实际内存时。)


正如其他答案所说,致电System.gc() 无济于事。这不太可能导致任何内存被归还。更糟糕的是,当垃圾级别太低而无法高效运行时,您很可能会运行 GC,因此您将无益地增加 CPU 时间。


关于你的“PS”:

  1. 我认为除了监控内存使用趋势之外,没有办法(可靠地)检测内存泄漏的存在。

  2. 我认为除了监控内存使用(和其他)趋势之外,没有办法(可靠地)预测您何时会购买新硬件。

  3. 我认为没有办法强制您的应用程序的内存使用量与用户数量成正比……除了设计/编码您的应用程序以便它以您想要的方式扩展之外。

另一方面,你可以对 C/C++ 应用程序说同样的话。

【讨论】:

    【解决方案3】:

    首先,如果您调用 System.gc(),您的空闲内存将如何提供帮助?并且调用 System.gc() 甚至不是一个好的选择。如果您想要一个更积极的垃圾收集器,那么有相应的策略。 你应该做的是使用 -Xmx 以更少的内存启动它

    【讨论】:

      【解决方案4】:

      不,不行。 System.gc() 不保证垃圾收集器是否/何时启动。此外,System.gc() 可能会调用垃圾收集器,这通常会导致垃圾收集所花费的时间比运行应用程序所花费的时间更多。

      解决方案是确定您的应用程序需要的最大内存量(占用空间),并以比占用空间稍多的内存启动虚拟机。我在这里假设您的应用程序没有内存泄漏。

      【讨论】:

        猜你喜欢
        • 2016-12-12
        • 1970-01-01
        • 2013-05-21
        • 1970-01-01
        • 2011-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多