【问题标题】:java : How to use heap beyond 4 GB memory in 32 bit JVMjava:如何在 32 位 JVM 中使用超过 4 GB 内存的堆
【发布时间】:2011-12-26 07:34:53
【问题描述】:

我们的产品目前在 32 位 1.6 JRE 上运行。我们使用的是 Berkeley DB,它在 4 GB 地址空间中消耗了大约 2.5 GB RAM。这给我们留下了大约 750 MB 的内存用于 JVM 地址空间。

我们目前遇到了当前设置的 OutOfMemory 问题。如果将我们的 JVM 堆大小增加到 1.5 GB,同时仍保留 Berkeley DB 的 2.5 GB 空间,那就太好了。有没有办法在 32 位 JVM 中访问超过 4 GB 的 RAM/堆?我正在考虑以下解决方案
1) 使用执行更好 GC 的 JVM——这会给我带来边际结果——我可以获得大约 50-100 MB 的工作内存
2) 诸如 memcached 或“进程外 ehcache”之类的东西——这可以让我得到硬件允许的 IPC/序列化开销。

还有其他解决方案可以增加应用程序的可寻址内存吗?

该解决方案应该适用于运行 sparc 的 solaris 10。

*更新:由于使用本机共享库,现在我们无法切换到 64 位 JVM,即使操作系统是 64 位 *

谢谢,

【问题讨论】:

  • 操作系统是带有大量 GB RAM 的 64 位 solaris。只有 java 进程需要更多 RAM/堆。
  • anjanb,你能说出 BerkeleyDB 的确切版本吗?为 BerkeleyDB 保留了多少内存?

标签: java memory jvm heap-memory solaris


【解决方案1】:

32 位程序无法处理超过 4GB 的内存地址。它们只是没有足够的位来表示更多的内存。

2^32 = 4 294 967 296

最好的办法是升级到 64 位 JRE。

【讨论】:

  • 由于使用了本机共享库,目前我们无法切换到 64 位 JVM,即使操作系统是 64 位的
  • @anjanb:在这种情况下,您可能必须按照 osgx 的建议将应用程序拆分为多个进程。
【解决方案2】:

还有其他解决方案可以增加应用程序的可寻址内存吗?

  1. 将单个应用程序拆分为具有非共享内存的多个进程(不是线程;而是进程)。第一个进程可以运行数据库,第二个可以运行项目的其他部分。您可以使用 RMI 或共享内存或套接字在进程之间进行通信。
  2. 较低的内存,为操作系统保留。例如。在 x86-32 PAE 上,操作系统可以保留小于 1 GB 的 4 GB 虚拟地址空间。 (例如“4GB / 4Gb 拆分”,Oracle Linux 支持)
  3. 将一些数据放入磁盘。磁盘可以是 RAM 磁盘以提高速度;或者它可以是真正的磁盘,操作系统将使用“页面缓存”加速对文件的访问。

此外,每个真正的 SPARC(不是古代的 SuperSparc 或穷人 LION)都是 64 位的。因此,切换到 64 位版本的操作系统会更容易。我不了解 Solaris,但在 linux 中,可以在 64 位操作系统之上运行 32 位应用程序。而 64 位操作系统将允许您运行 64 位 JVM。

更新:Solaris http://wikis.sun.com/display/BigAdmin/Talking+about+RAM+disks+in+the+Solaris+OS 中有 ramdisk,我认为您应该尝试使用它们来存储数据库(或 DB 的临时文件)。 不会像情况(1)那样有额外的序列化/IPC;只有额外的读/写或 mmap/munmap。但 Ramdisk 的订购速度比 SSD 快,比 HDD 快 3-4 个订单。

【讨论】:

  • 由于使用了本机共享库,目前我们无法切换到 64 位 JVM,即使操作系统是 64 位的
  • 你能将原生库移动到分离的进程吗?您是否尝试在 64 位操作系统上运行 32 位 JVM(这有助于不需要 2/2 或 3/1 GB 拆分)?
  • 有一个快速测试来检查内存拆分方案:stackoverflow.com/questions/987219/… - 您可以在当前环境和 64-bitOS + 32bit JVM 组合中运行它
  • 如果他已经获得了 3.2gb 的地址空间,他已经在他运行的任何操作系统上使用了你的第二个点(windows 也有类似的东西)。虽然我不明白为什么在这种情况下 64 位操作系统不会给他整个 32 位地址空间 - 奇怪 (at least windows should make the whole 4gb available in that case)。
  • 我们在 64 位操作系统上运行 32 位 JVM -- solaris
【解决方案3】:

我建议您在 32 位 JVM 中运行您的 32 位共享本机库,并在 64 位 JVM 中运行其他所有内容。您可以让 64 位 JVM 调用 32 位 JVM 来完成它所做的任何事情。我假设您的大部分数据/内存需求可以转移到 64 位 JVM。

【讨论】:

  • 这是我们必须试验的东西,看看它是否对系统预期的吞吐量有意义。
  • 您应该能够在同一台机器上的两个进程之间实现 500 MB/s 到 3000 MB/s 的吞吐量(取决于您的硬件)。
  • 你能建议 64 位 Java 应用程序与 32 位 Java 应用程序对话的最佳方法吗?我知道通常的 unix/linux IPC 机制,但哪些在 64 位 java 和 32 位 java 场景中效果最好?
  • JVM 的位数无关紧要。我会使用使用阻塞 IO 的普通 Socket,或者 NIO 可能是最简单的。您可以将 DataOutput/InputStream 与 IO 或 ByteBuffers 与 NIO 一起使用。您可以通过单个 TCP 连接每秒发送数百万条消息,往返延迟低于 20 微秒。
猜你喜欢
  • 1970-01-01
  • 2017-06-05
  • 2012-04-04
  • 2020-01-11
  • 1970-01-01
  • 1970-01-01
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多