-d64开关对Sun JVM常驻内存使用有什么影响(如果有的话)?

11

我有一个需要进行内存优化的Web应用程序。虽然我已经在对应用程序进行分析和优化,但是我们最繁忙的实例中JVM本身似乎对我来说过于臃肿。(低容量实例没有这个问题。)详情如下:

  • 平台:
    • RHEL4 64位 (Linux 2.6.9-78.0.5.ELsmp #1 SMP x86_64)
    • Sun Java 6 (Java HotSpot(TM) 64-Bit Server VM (build 10.0-b23, mixed mode))
    • 带有-d64的Tomcat 6 startup.sh
  • 我的Web应用程序目前有一些代码,在生产中需要运行在64位模式下。
  • 我观察到,经过一段时间(一周),JVM 的常驻内存大小(如 top 所示)是我的 -Xmx 设置大小的三倍
  • 非堆内存大小等都相对较小,只占堆大小的百分之几。
  • 只有一个代码部分需要使用64位地址空间。

如果我可以重构掉对64位JVM的需求,并删除-d64开关,那么JVM的常驻内存占用会变小吗?换句话说...

对于Sun JVM的常驻内存使用情况,-d64开关有什么影响(如果有)?

1个回答

18

使用d64开关可以将JVM设置为64位模式。在Solaris / Linux和大多数Unix系统上,JVM进程将以LP64模型执行。

LP64模型与32位模型(ILP32)不同,因为指针恰好为64位宽而不是32位指针。对于JVM来说,这允许更大的内存可寻址性,但也意味着仅对象引用占用的大小已经翻倍。因此,在32位JVM和64位JVM中,在给定时间内具有相同数量的对象会出现更大的膨胀。

另一个经常被遗忘的事情是指令本身的大小。在64位JVM上,指令的大小将占用本地机器寄存器的大小。

然而,如果您在64位环境中使用压缩对象指针,则JVM将在堆大小大于4 GB时尝试编码和解码指针。简而言之,当您使用压缩指针时,JVM会尽可能使用32位宽度的值。

提示:打开UseCompressedOops标志,使用-XX:+UseCompressedOops来减少一些膨胀。YMMV,但有人报告通过使用压缩的oops可以减少高达50%的内存膨胀

编辑

在Java HotSpot VM的14.0版本中,支持UseCompressedOops标志,可从Java 6更新14开始使用


太棒了!你已经说服我重构我的代码并且放弃使用-d64。我会回来评论它的效果。我也会更新JVM以便尝试-XX:+UseCompressedOops。谢谢。你赢得了2009年9月份Stu世界著名的“月度最佳程序员”奖项! - Stu Thompson
超级靠谱!!! 我自己也查了一下,觉得付出的努力是值得的...但是有太多的JVM开关、参数、if-then-but情况和陷阱。这可能会让人感到不知所措,而我需要的是一个“做/不做”的答案,并配以相关的详细指导。再次感谢。 - Stu Thompson
顺便提一下:超过4GB的不是我的堆,而是我使用的MappedByteBuffers使用了超过4GB的地址空间。当时这似乎是个好主意... - Stu Thompson
4
关于UseCompressedOops标志:"在Java SE 6u23及更高版本中,默认支持并启用压缩oops。在Java SE 7中,当未指定-Xmx和-Xmx的值小于32GB时,64位JVM进程默认使用压缩oops。对于6u23版本之前的JDK 6,请在java命令中使用-XX:+UseCompressedOops标志启用该功能。" 来源:http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html - Julien Chastang
自6u23版本起,该标志现在默认已启用。 - Riking
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接