Java 为什么这个系统会这样。gc()似乎对某些JVM没有影响

Java 为什么这个系统会这样。gc()似乎对某些JVM没有影响,java,memory,memory-management,jvm,Java,Memory,Memory Management,Jvm,我一直在开发一个小型Java实用程序,它使用两个框架:Encog和Jetty为网站提供神经网络功能 代码“完成”了,因为它完成了所有需要做的事情,但是我在内存使用方面遇到了一些问题。在我的开发机器上运行时,当应用程序运行时(训练神经网络),内存使用量似乎在4MB到13MB之间波动,最多使用18MB左右。这是一个非常好的用法,我认为这是因为我经常调用System.GC()。我这样做是因为处理时间对我来说并不重要,但内存使用情况却很重要 所以它在我的机器上运行得很好,但一旦我把它放到我们的服务器上(

我一直在开发一个小型Java实用程序,它使用两个框架:Encog和Jetty为网站提供神经网络功能

代码“完成”了,因为它完成了所有需要做的事情,但是我在内存使用方面遇到了一些问题。在我的开发机器上运行时,当应用程序运行时(训练神经网络),内存使用量似乎在4MB到13MB之间波动,最多使用18MB左右。这是一个非常好的用法,我认为这是因为我经常调用System.GC()。我这样做是因为处理时间对我来说并不重要,但内存使用情况却很重要

所以它在我的机器上运行得很好,但一旦我把它放到我们的服务器上(有内存限制的共享unix主机),它就开始使用大约19MB的内存,并且在做事情时会增加到数百MB的内存使用量。这些都是我在测试中一直在做的事情。我认为,减少内存使用的唯一方法是退出应用程序并重新启动它

我能说的唯一区别是它正在运行的Java虚拟机。我不知道这一点,我试图找到它这样做的原因,但是很多文档假定它对Java和虚拟机有很好的了解。有没有人能帮我解释一下为什么会发生这种情况,或者是一些事情来阻止它

我已经考虑过使用GCJ编译应用程序,但我不知道这是否是我应该投入大量时间的事情,以及它是否真的有帮助

谢谢你的帮助

  • 更新:在MacOS10.6.3上开发,服务器在unix操作系统上,但我不知道是什么。(服务器来自WebFaction)
我想这是因为我 定期调用System.GC()

你不应该那样做,这几乎没有用

当垃圾收集器有大量内存可供使用时,它的工作效率最高,因此它将倾向于使用它所能获得的大部分内存。我认为您所需要做的就是使用
-Xmx32m
命令行参数将最大堆大小设置为32MB—默认值取决于JVM是否认为它正在“服务器类”系统上运行,在这种情况下,它假设您希望应用程序使用尽可能多的内存以提供更好的吞吐量


顺便说一句,如果您在服务器上的64位JVM上运行,由于较大的引用,它将合理地需要比32位JVM更多的内存(通常约30%)。

您可以考虑以下两点:

  • 调用
    System.gc
    可以通过命令行参数(-XX:-DisableExplicitGC)禁用,我认为这种行为还取决于vm使用的gc算法。通常,调用gc应该留给jvm
  • 只要jvm有足够的可用内存,我就看不出使用此内存来提高应用程序和gc性能有任何错误。正如michaelborgwardt所说,您可以在命令行上限制vm使用的内存量

此外,您可能希望了解在联机部署JVM时JVM是以何种模式启动的。我猜这是一个服务器虚拟机。
请看一下stackoverflow上这两者之间的距离。另外,请查看实际部署中实际运行的垃圾收集器。查看是否可以查看GC行为或更改GC算法。如果是Sun JVM,请查看-X选项。

基本上JVM会根据需要获取允许的内存量,以便尽可能快地执行“新”操作(这本身就是一门科学)

因此,如果你有很多对象被使用,然后被丢弃,你会慢慢地、肯定地填满可用的内存。然后,您可以请求垃圾收集,但这只是一个提示,JVM可能会选择不侦听

因此,您需要另一种机制来降低内存使用率。典型的方法是使用-Xoptions限制内存量,但要小心,因为您在pc上使用的JVM可能与您部署的JVM非常不同,因此内存需求可能不同


是否有意要求低内存使用率?如果没有,就让它运行,看看JVM的行为。使用jvisualvm进行连接和监视。

也许服务器使用了更多内存,因为您的应用程序负载更高,因此使用了更多线程?如果有很多请求,Jetty将使用许多线程来分散负载。值得一看服务器上的线程数与测试机器上的线程数。

您的开发环境是Windows还是Linux?是在Mac OS 10.6上开发的。对不起,我是故意这么说的。理想情况下,RAM的使用量不能超过40MB。这就是我必须在服务器上为这个应用程序处理的问题。我假设服务器是64位的,但是强制它使用32位虚拟机是否可行/可取?当我说在测试中RAM的使用量在4到13MB之间波动时,我相信每次调用System.GC()时,RAM的使用量都会从13下降到大约4,但我不确定。所以放-Xmx40m-Xms40m,您的程序将始终使用正好40M的RAM。然后删除对System.gc的所有调用,因为这是糟糕的Java风格。JVM将为您处理GC,只需给它必须使用的内存边界(如我上面所建议的)好的,谢谢,我将尝试这个。我认为System.GC()不是个好主意。做了一点C#之后,我就再也不会这样做了,当我用Java做这件事时,它看起来像是一个“黑客”,但它似乎很有帮助。由于java 6u14的64位虚拟机有一个非常酷的特性,名为“压缩对象指针”,在堆大小<32GB的情况下,引用仍然只使用32位。详细信息位于和@Jörn,您在生产中使用过此功能吗?如果我限制可用内存量,如果应用程序通常希望使用更多内存,会发生什么情况?它会崩溃还是就这样