我尝试比较我的 Java Web 应用程序在 32 位 Windows 和 64 位 Linux 上的行为。
当我通过 jconsole 查看内存使用情况时,我发现内存使用情况的图表非常不同。 在 Windows 上,应用程序永远不会触及 512m。 然而,当我在带有 64 位 VM 的 linux 64 位上运行时,内存不断增加并很快达到约 1000m 的峰值,并且我还收到与超出 GC 超额限制相关的 oome 错误。在 Linux 上,每当我手动运行 GC 时,它就会下降到不到 100m。
GC 看起来确实像在 Windows 上运行得那么好。
在 Windows 上,应用程序在负载更大的情况下运行得更好。
如何找到这背后的原因?
我使用jdk1.6.0.13
最小堆:512m,最大堆1024m
编辑:
您在 Windows 和 Linux 上使用相同的 JVM 版本吗?
- 是。1.6.0.13。
您在两个系统上使用相同的垃圾收集器吗?
- 我注意到 jconsole 中的 gc 是不同的。
您在两个系统上使用相同的 Web 容器吗?
- 是的,Tomcat。
您的网络应用程序是否依赖 native 库?
- 不确定。我用的是tomcat+spring+hibernate+jsf。
这两个平台上的 Web 应用程序配置还有其他差异吗? 没有
与 OOME 相关的错误消息到底是什么?
- java.lang.OutOfMemoryError:超出 GC 开销限制
您的网络应用程序需要多长时间才能在 Linux 上开始行为不当/报告错误?
- 在我让其运行 3 小时后,可以看到使用模式的差异。该错误大约在一天或两天后出现,因为此时平均内存使用量约为 900 MB。
最佳答案
64 位 JVM 自然会比 32 位 JVM 使用更多的内存,这是可以预料的(毕竟,内部指针的大小是其两倍)。从 32 位迁移到 64 位时,您无法保持相同的堆设置并期望出现相同的行为。
如果您的应用程序在 32 位 JVM 上以 512m 的速度运行良好,则没有任何理由使用 64 位 JVM。这样做的唯一理由是利用巨大的堆大小。
请记住,在 64 位操作系统上运行 32 位 JVM 是完全有效的。两者没有关系。
关于java - 64 位 Linux 上的意外 JVM 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3378749/