5

我正在开发一个 clojure 应用程序,它似乎使用了比它应该使用的更多的内存。我认为这是内存泄漏,但在使用 jvisualvm 查看后,似乎 GC 运行的频率不够高。红色轮廓是我手动调用 GC 的地方。为什么它似乎在使用 30mb 左右时分配 300mb?

4

3 回答 3

5

如果您认为堆太大,请使您的堆更小。GC 只在必要时运行。

(多年来,控件发生了变化,但我认为它们仍然是初始堆大小、增量大小和最大大小。如果您的初始堆大小很小,只要没有堆使用中的“高水位线”将其推高。)

于 2012-09-28T18:27:44.980 回答
5

JVM 具有调节内存管理的参数,包括初始分配的数量和要分配的最大数量。除了这些参数,JVM 无法知道您认为合理的内存使用量。据我所知,JVM 没有要求按任何特定的时间表运行 GC,也没有任何目标内存使用量是 Java 定义的一部分。

假设您说 JVM 可用的最大内存是 100 MB,而您目前正在使用 50 MB,包括死对象。您有一个需要 1 MB 的 NEW。JVM 应该运行 GC 吗?这不是必需的:在达到最大值之前您有足够的空间。这是个好主意吗?这很难说。使用大量内存或执行大量 GC 哪个更糟?

作为 Java 程序员,您通常不应该知道或关心。只要它在声明你内存不足之前进行一次GC,它有什么区别?如果您的应用程序使用的内存过多,以至于其他应用程序无法分配所需的内存,则可以更改运行时参数以减少您将使用的最大值。那应该是重要的事情的极限。

于 2012-09-28T18:29:06.037 回答
4

JVM 使用分代垃圾收集器。如果您通常在任何给定时间都有大约 30MB 的内容,也许您应该将新一代大小设置为 60MB 左右。这样垃圾收集器应该在它们被提升到老一代之前收集你之前传递的所有东西(收集的频率要低得多)。

Sun/Oracle JVM有大量的性能调整选项。您可能要为此设置-XX:NewSize=60m

你想设置哪个选项我可能是错误的——可能有一个更适合这个问题。但是,我认为使用这些 GC 标志进行调整是一个比其他答案中建议的仅仅减少总堆大小更好的选择。

更新:这是我在设置特定于生成的堆大小的主题上找到的更多信息:

调优 JVM:指定堆大小值

于 2012-09-28T18:42:54.317 回答