这是我的情况:我手头有一项需要大量记忆的任务.我没有足够的ram,无论我尝试了什么(Jrockit和/ 3gb交换机等),我都不能给JVM足够的ram并且操作以异常终止,告诉我需要更多的堆空间.
有什么方法可以强制JVM使用操作系统的交换机制,以便它不会耗尽内存?这是Windows xp 32位
这需要很长时间,但我不在乎,我只需要完成这项操作.
我的选项用完了,而且我无法控制任何变量.
这是一个必需的编辑,因为我几乎每个人都有相同的响应:)这不是我的代码.有人编写了一个将xml文件读入存储库的工具.该工具使用EMF,并立即加载整个模型.我所能做的就是为它提供XML文件.如果本机代码在Windows或Linux等下运行,操作系统会使用虚拟内存/交换空间为其提供内存,而应用程序并不知道它.我想知道是否可以对JVM做同样的事情.在Windows 32位下,-Xmx可以达到一定数量,但这还不够.出门购买新硬件暂时不适合我.所以我想知道是否有可能使JVM像本机进程一样工作.慢,但仍在工作.显然这是不可能的,我运气不好.我只需要知道我是否真的没有选择权.
rod*_*ion 10
显然,有一种方法可以绕过Java堆的限制.它甚至被用在名为BigMemory的商业产品中,它基本上允许您通过透明地交换到OS交换和/或磁盘(如果需要)来拥有几乎无限的内存.
我们的想法是使用direct ByteBuffers来存储您的对象数据.因为直接字节缓冲区的内容存储在本机进程内存中(而不是堆),所以可以依靠操作系统交换机制为您交换内存.我在这个网站上找到了这个(在页面上搜索'direct byte buffer').
以下是如何实现它(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){ ... }
}
Run Code Online (Sandbox Code Playgroud)
希望你明白这个主意.你只需要实现序列化(你也可以使用zip来压缩你的对象.如果你有很少的大对象,特别是包含像字符串这样的可拉伸数据的对象,这将是有效的).
当然NativeMemoryCache对象,data哈希映射和keys将在堆中,但这不应占用太多内存.
正如其他答案所指出的,您可以使用该-Xmx开关为JVM提供更多RAM.
但是,你可以走多远就有限制.在32位系统上,如果JVM支持它,它可能是2GiB,可能是3或4 GiB.对于Sun JVM,根据Java -Xmx,系统上的Max内存, 32位Windows上的限制为1500MiB .
出于基本的架构原因,进程不能(没有特殊技术)获得超过4 GiB的内存(包括它可能使用的任何交换空间),这就是-Xmx存在值限制的原因.
如果您已尝试了最大可能值,但仍然会出现OOM错误,那么您唯一的选择是:
要么
-Xmx进一步增加编辑:
请注意,4 GiB限制是CPU体系结构的限制,因此它适用于任何进程,Java或不适用.因此,即使是原生分配技巧也无法帮到你.唯一的解决方法是使用多个进程,但这需要对应用程序进行基本的重写,这可能就像修复应用程序以减少RAM一样复杂.所以上面的两个选项是你唯一的(明智的)选择.
编辑2:
要解决问题的新部分:
我想知道是否有可能使JVM像本机进程一样工作.
这是一种误解.在这方面,JVM 确实像本机进程一样工作:它使用的堆位于JVM从OS分配的内存中; 对于操作系统来说,这只是分配了内存,操作系统会像任何其他内存一样将其交换出来 - 如果感觉就好 - 这没什么特别的.
堆无法无限增长的原因并不是它不能大于物理RAM(它可以,我至少在Linux/x86上尝试过),但每个操作系统进程(JVM都是)不能超过4GiB内存.所以在32位系统上,你永远不会有超过4GiB堆.在实践中,它可能要少得多,因为堆内存不能被分段(参见例如Windows XP上的Java最大内存),但4GiB是一个难以避免的限制.