我正在开发一个clojure应用程序,它似乎使用了比它应该多得多的内存。我认为这是一个内存泄漏,但在用jvisualvm查看后,似乎GC运行得不够频繁。红色轮廓是我手动调用GC的地方。为什么它似乎在使用大约30mb时分配300mb?
答案 0 :(得分:5)
如果您认为它太大,请将您的堆缩小。 GC仅在必要时运行。
(这些控件多年来一直在变化,但我认为它们仍然是初始堆大小,增量大小和最大大小。如果你的初始堆大小很小,它会保持很小这么久因为堆使用中没有“高水位线”可以将其推高。)
答案 1 :(得分:5)
JVM具有调节内存管理的参数,包括最初分配的数量和要分配的最大数量。除了这些参数之外,JVM无法知道您认为合理使用的内存量。据我所知,没有要求JVM在任何特定的时间表上运行GC,也没有任何目标内存使用量是Java定义的一部分。
假设您已经说过JVM可用的最大内存是100 MB,而您目前使用的是50 MB(包括死对象)。你有一个需要1 MB的新功能。 JVM应该运行GC吗?这不是必要的:在你达到最大值之前你有足够的空间。这是个好主意吗?这很难说。更糟糕的是,要使用大量内存还是要做很多GC?
作为Java程序员,您通常不应该知道或关心。只要它在宣布你的内存不足之前做GC,它会有什么不同?如果您的应用程序使用了大量内存而其他应用程序无法分配所需内容,那么请更改运行时参数以减少您将采用的最大值。这应该是重要的限制。
答案 2 :(得分:4)
JVM使用分代垃圾收集器。如果您在任何给定时间通常有大约30MB的东西,也许您应该将新一代大小设置为60MB。这样,垃圾收集器应该收集你之前传递的所有东西,然后才能升级到老一代(收集的次数要少得多)。
Sun / Oracle JVM有一大堆performance tuning options。您可能想为此设置-XX:NewSize=60m
。
我可能错误地想要设置哪个选项 - 可能有一个更适合此问题的选项。但是,我认为使用这些GC标志进行调整是一个更好的选择,而不是像其他答案中建议的那样减少总堆大小。
更新: 以下是我在设置特定于生成的堆大小主题上找到的更多信息: