无论内存需求有多大,有没有办法强制 JVM 使用交换区?

发布于 2024-10-10 06:23:01 字数 578 浏览 0 评论 0原文

这是我的情况:我手头有一项需要大量内存的任务。我没有足够的内存,无论我尝试什么(使用 /3gb 开关的 Jrockit 等),我都无法为 JVM 提供足够的内存,操作会因异常而终止,告诉我需要更多的堆空间。

有什么方法可以强制 JVM 使用操作系统的交换机制,这样它就不会耗尽内存吗?这是 Windows xp 32 位

这需要很长时间,但我不在乎,我只需要完成这个操作。

我已经没有选择了,而且我无法控制这里的任何变量。

这是一个必需的编辑,因为我几乎每个人都得到了相同的回应:) 这不是我的代码。有人编写了一个工具,可以将 xml 文件读入存储库。该工具使用 EMF,并立即加载整个模型。我所能做的就是向它提供 XML 文件。 如果本机代码在 Windows 或 Linux 等环境下运行,操作系统会使用虚拟内存/交换空间为其提供内存,而应用程序并不知道这一点。 我想知道是否可以用 JVM 做同样的事情。在 Windows 32 位下,-Xmx 可以达到一定的数量,但这还不够。 目前我还不能选择出去购买新硬件。所以我想知道是否有可能让 JVM 像本机进程一样工作。缓慢,但仍在工作。 显然这是不可能的,我很不幸。我只需要知道我是否真的别无选择。

Here is my situation: I have a task at hand that requires lots of memory. I do not have enough ram, and no matter what I tried (Jrockit with /3gb switch etc), I can't give JVM enough ram and the operation is terminated with an exception, telling me I need more heap space.

Is there any way I can force the JVM to use the OS's swapping mechanism so that it won't run out of memory? This is Windows xp 32 bit

It would take ages, but I would not care, I just need this operation to be completed.

I've run out of options, and I have no control over any of the variables here..

This is a required edit, since I am having the same response from pretty much everyone :)
This is not my code. Someone has written a tool that reads an xml file into a repository. The tool uses EMF, and loads the whole model at once. All I can do is to feed it the XML file.
In case of native code running under Windows or Linux etc, the OS provides memory to it, using virtual memory/swap space, and the app does not know about it.
I was wondering if it is possible to do the same with the JVM. Under Windows 32 bit, -Xmx can go up to a certain amount, but that is not enough.
Going out and buying new hardware is not an option for me for the moment. So I was wondering if it is possible to make the JVM work like native processes. Slow, but still working.
Apparently that is not possible, and I am out of luck. I just need to know if I'm really out of options.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天暗了我发光 2024-10-17 06:23:01

显然有一种方法可以绕过 Java 堆的限制。它甚至被用在名为 BigMemory 的商业产品中,它基本上允许您通过透明交换来拥有几乎无限的内存如果需要的话,到操作系统交换和/或磁盘。

这个想法是使用直接的 ByteBuffer 来存储对象数据。由于直接字节缓冲区的内容存储在本机进程内存中(而不是堆),因此您可以依靠操作系统交换机制来为您交换内存。我在此网站上找到了这个(在页)。

以下是如何实现它(java-pseudo-code'ish):

class NativeMemoryCache{
  private Map<Object, ByteBuffer> data = new HashMap<...>();

  public void put(Object key, Serializable object){
    byte[] bytes = serialize(object);
    //allocate native memory to store our object
    ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
    buf.put(bytes);
    buf.flip();
    data.put(key, buf);
  }

  public Object get(Object key){
    ByteBuffer buf = data.get(key).duplicate();
    byte[] bytes = new byte[buf.remaining()];
    buf.get(bytes);
    return deserialize(bytes);
  }

  private byte[] serialize(Object obj){ ... }
  private Object deserialize(byte[] bytes){ ... }
}

希望您明白了。您只需要实现序列化(您还可以使用 zip 压缩对象。如果您只有很少的大对象,尤其是包含可压缩数据(例如字符串)的对象,这将非常有效)。

当然,NativeMemoryCache 对象、data 哈希映射和 key 将位于堆中,但这不会占用太多内存。

Apparently there is one way around the limits of Java heap. It is even used in a commercial product called BigMemory which basically allows you to have almost unlimited memory by transparently swapping out to OS swap and/or to disk if needed.

The idea is to use direct ByteBuffers to store your objects data. Because direct byte buffers' contents are stored in native process memory (as opposed to heap) you can rely on OS swap mechanism to swap memory out for you. I found this on this website (search for 'direct byte buffer' on the page).

Here is how you can implement it (java-pseudo-code'ish):

class NativeMemoryCache{
  private Map<Object, ByteBuffer> data = new HashMap<...>();

  public void put(Object key, Serializable object){
    byte[] bytes = serialize(object);
    //allocate native memory to store our object
    ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
    buf.put(bytes);
    buf.flip();
    data.put(key, buf);
  }

  public Object get(Object key){
    ByteBuffer buf = data.get(key).duplicate();
    byte[] bytes = new byte[buf.remaining()];
    buf.get(bytes);
    return deserialize(bytes);
  }

  private byte[] serialize(Object obj){ ... }
  private Object deserialize(byte[] bytes){ ... }
}

Hope you get the idea. You just need to implement the serialization (you can also compress your objects using zip. This will be effective if you have few big objects especially ones containing zippable data like strings).

Of course NativeMemoryCache object, data hash map and keys will be in heap, but that should not take much memory.

过度放纵 2024-10-17 06:23:01

正如其他答案所指出的,您可以使用 -Xmx 开关为 JVM 提供更多 RAM。

但是,您可以达到的高度是有限的。在 32 位系统上,这可能是 2GiB,如果 JVM 支持的话,可能是 3 或 4 GiB。对于 Sun JVM,根据 Java -Xmx, Max,32 位 Windows 上的限制为 1500MiB系统内存

出于基本架构原因,进程无法(无需特殊技术)获得超过 4 GiB 的内存(包括它可能使用的任何交换空间),这就是 -Xmx 价值观存在。

如果您已尝试最大可能值,但仍然出现 OOM 错误,那么您唯一的选择是:

  • 修复应用程序,使其需要更少的 RAM

  • 将其移至 64 位操作系统,并进一步增加 -Xmx

编辑:

请注意,4 GiB 限制是 CPU 架构的限制,因此它适用于任何进程,无论是否为 Java。因此,即使是本机分配技巧也无法帮助您。解决这个问题的唯一方法是使用多个进程,但这需要对应用程序进行根本性的重写,这可能会像修复应用程序以使用更少的 RAM 一样复杂。所以上面的两个选项是你唯一的(明智的)选择。

编辑2:

要解决问题的新部分:

我想知道是否可以
让 JVM 像原生一样工作
流程。

这是一个误解。在这方面,JVM确实像本机进程一样工作:它使用的堆位于 JVM 从操作系统分配的内存中;对于操作系统来说,这只是分配的内存,操作系统会像任何其他内存一样将其交换出来(如果需要的话)——这没有什么特别的。

堆不能无限增长的原因并不是它不能大于物理 RAM(可以,我至少在 Linux/x86 上尝试过),而是每个操作系统进程(JVM 就是)不能获得超过 4GiB内存。因此,在 32 位系统上,堆永远不能超过 4GiB。在实践中,它可能会少得多,因为堆内存一定不能碎片化(参见例如 Java Windows XP 上的最大内存),但 4GiB 是一个硬性的、不可避免的限制。

As pointed out by the other answers, you use the -Xmx switch to give more RAM to the JVM.

However, there's a limit on how high you can go. On a 32bit system, this will probably be 2GiB, maybe 3 or 4 GiB if the JVM supports it. For the Sun JVM, the limit is 1500MiB on 32bit Windows, according to Java -Xmx, Max memory on system .

For fundamental architectural reasons, a process cannot (without special techniques) get more than 4 GiB of memory (including any swap space it may use), that's why the limit on -Xmx values exists.

If you have tried the maximum possible value, and still get OOM Errors, then your only options are:

  • fix the application so it needs less RAM

or

  • move it to a 64bit OS, and increase -Xmx even further

Edit:

Note that the 4 GiB limit is a limitation of the CPU architecture, so it applies to any process, Java or not. So even native allocation tricks won't help you here. The only way around it is to use more than one process, but that would require a fundamental rewrite of the application, which would probably be as complicated as just fixing the app to use less RAM. So the two options above are your only (sensible) options.

Edit 2:

To address the new part of your question:

I was wondering if it is possible to
make the JVM work like native
processes.

This is a misunderstanding. The JVM does work like native process in this respect: The heap it uses is located in memory allocated from the OS by the JVM; to the OS this is just allocated memory, and the OS will swap it out like any other memory if it feels like it - there is nothing special about this.

The reason that the heap cannot grow indefinitely is not that it cannot be larger than physical RAM (it can, I have tried it at least on Linux/x86), but that each OS process (which the JVM is) cannot get more than 4GiB RAM. So on 32bit systems you can never have more than 4GiB heap. In practice, it may be much less because the heap memory must not be fragmented (see e.g. Java maximum memory on Windows XP ), but the 4GiB is a hard, unavoidable limit.

影子是时光的心 2024-10-17 06:23:01

根据我的经验,JVM 从操作系统请求内存,操作系统可以将其分配在 RAM 中的交换区中。这取决于你有多少资源。您可以在 java 中分配的内存并不取决于您的 RAM,而是取决于您在运行 JVM 时指定的命令行选项 -Xmx。例如,如果 RAM 内存不足,JVM 从交换区接收它,(我相信)甚至不知道这一点。

顺便说一句,恕我直言,您实际上并不需要那么多内存。我同意那些人的说法。我建议你检查一下你的设计。

According to my experience JVM requests memory from OS that can allocate it either in RAM in swap. It depends on how much resources do you have. The memory you can allocate in java does not depend on your RAM but on command line option -Xmx you specify when you are running your JVM. If for example it is not enough memory in RAM JVM receives it from swap and (I believe) even does not know about that.

BTW IMHO you do not really need so much memory. I am agree with guys that said that. I'd suggest you to review your design.

所谓喜欢 2024-10-17 06:23:01

如果您没有足够的 RAM,则需要更改代码,以便应用程序适合内存。如果您使 JVM 足够大,以至于它必须将应用程序交换到磁盘,那么它就会挂起。 JVM 中的堆并非设计为脱离磁盘运行。

我怀疑你遇到的问题是你无法分配足够的连续内存,而这是 JVM 的要求。当您使用更多的可用内存时,在 32 位操作系统中获得大的连续内存块会变得更加困难。

现在要么是获得更多内存的时候,但现在内存相对便宜。或减少您的内存需求。使用交换将需要很长时间才能完成。

顺便说一句:您可以花费大约 1,800 英镑购买 24 GB 服务器,花费大约 4,200 英镑购买 64 GB 服务器。只需花费 53,000 英镑,您就可以获得一台内存为 1 TB 的服务器! :D

If you don't have enough RAM you need to change your code so the application fits into memory. If you make the JVM large enough that it has to swap to disk the application it will as good as hang. The heap in the JVM is not designed to run off disk.

I suspect the problem you have is that you cannot allocate enough continuous memory which is a a requirement for the JVM. As you use more of the available memory, it is harder to get a large continuous memory block with an 32-bit OS.

It is either time to get more memory, which is relatively cheap these days. or reduce your memory requirement. Using swap will just take forever to complete.

BTW: You can buy a 24 GB server for about £1,800 and 64 GB server for about £4,200. For £53,000 you can get a server with 1 TB of memory! :D

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文