这是我的情况:我手头有一项需要大量内存的任务。我没有足够的内存,不管我怎么尝试(Jrockit和/3gb开关等),我都不能给JVM足够的内存,操作就会因为一个异常而终止,告诉我我需要更多的堆空间。
有没有办法强制JVM使用操作系统的交换机制,这样它就不会耗尽内存?这是Windows xp 32位
这将需要很长时间,但我不会在意,我只需要完成这个操作。
我已经没有选择了,并且我无法控制这里的任何变量。
这是一个必需的编辑,因为我几乎每个人都有相同的回应:)这不是我的代码。有人编写了一个工具,可以将xml文件读入存储库。该工具使用EMF,并一次性加载整个模型。我所能做的就是将XML文件提供给它。对于在Windows或Linux等操作系统下运行的本机代码,操作系统使用虚拟内存/交换空间为其提供内存,而应用程序并不知道这一点。我想知道是否有可能对JVM做同样的事情。在Windows32位下,-Xmx可以达到一定的数量,但这还不够。出去购买新硬件目前对我来说不是一个选择。所以我想知道是否有可能让JVM像本机进程一样工作。速度很慢,但仍在工作。显然这是不可能的,而且我也不走运。我只想知道我是否真的别无选择。
发布于 2011-01-03 22:11:11
显然,有一种方法可以绕过Java堆的限制。它甚至被用于一个名为BigMemory的商业产品中,它基本上允许您通过透明地交换到操作系统交换和/或磁盘(如果需要)来拥有几乎无限的内存。
这个想法是使用直接ByteBuffer来存储您的对象数据。因为直接字节缓冲区的内容存储在本机进程内存中(而不是堆中),所以您可以依靠操作系统交换机制来为您交换内存。我在this website上找到了这个(在页面上搜索“直接字节缓冲区”)。
下面是你如何实现它(java伪代码):
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散列映射和keys将在堆中,但这应该不会占用太多内存。
发布于 2011-01-03 19:57:57
正如其他答案所指出的,您可以使用-Xmx开关为JVM提供更多内存。
然而,你能达到的高度是有限制的。在32位系统上,这可能是2GiB,如果JVM支持的话,可能是3或4 GiB。根据Java -Xmx, Max memory on system的说法,对于Sun,在32位Windows上的限制是1500MiB。
由于基本的体系结构原因,一个进程(没有特殊技术)不能获得超过4 GiB的内存(包括它可能使用的任何交换空间),这就是存在-Xmx值限制的原因。
如果您已经尝试了最大可能值,但仍然得到OOM错误,则您唯一的选择是:
或
-Xmx 编辑:
请注意,4cpu的限制是GiB架构的一个限制,因此它适用于任何进程。因此,即使是本机分配技巧在这里也不会对您有所帮助。绕过它的唯一方法是使用多个进程,但这将需要从根本上重写应用程序,这可能会像修复应用程序以使用更少的RAM一样复杂。所以上面的两个选项是你唯一(明智的)选择。
编辑2:
为了回答你问题的新部分:
我想知道是否有可能让
像本机进程一样工作。
这是一个误解。在这方面,JVM确实像本机进程一样工作:它使用的堆位于由JVM从OS分配的内存中;对于OS来说,这只是分配给它的内存,OS会像任何其他内存一样交换它-这没有什么特别的。
堆不能无限增长的原因不是因为它不能大于物理RAM (它可以,我至少在Linux/x86上尝试过),而是每个OS进程( JVM就是这样)不能获得超过4GiB的RAM。因此,在32位系统上,您永远不能拥有超过4GiB的堆。在实践中,它可能会少得多,因为堆内存不能是碎片的(例如,参见Java maximum memory on Windows XP ),但4GiB是一个硬的、不可避免的限制。
发布于 2011-01-03 19:37:17
根据我的经验,JVM从OS请求内存,OS可以在交换的RAM中分配内存。这取决于你有多少资源。在java中可以分配的内存并不取决于内存,而是取决于在运行JVM时指定的命令行选项-Xmx。例如,如果RAM中没有足够的内存,JVM从交换空间接收它,并且(我相信)甚至不知道这一点。
顺便说一句,你并不真的需要这么多内存。我同意那些人说的话。我建议你重新审视一下你的设计。
https://stackoverflow.com/questions/4583995
复制相似问题