首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在使用java.nio.MappedByteBuffer时防止OutOfMemory

在使用java.nio.MappedByteBuffer时防止OutOfMemory
EN

Stack Overflow用户
提问于 2011-12-19 00:41:35
回答 4查看 8.2K关注 0票数 5

考虑创建5-6个线程的应用程序,每个线程在周期中为5mb的页面大小分配MappedByteBuffer。

代码语言:javascript
运行
复制
MappedByteBuffer b = ch.map(FileChannel.MapMode.READ_ONLY, r, 1024*1024*5);

当应用程序处理大文件时,oom迟早会抛出。

代码语言:javascript
运行
复制
java.io.IOException: Map failed  at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:758)
Caused by: java.lang.OutOfMemoryError: Map failed
        at sun.nio.ch.FileChannelImpl.map0(Native Method)
        at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:755)

根据规范,一旦MappedBuffer成为GC本身,就应该立即处理直接内存。看起来问题是,MappedBuffer的GC-s太晚了,然后直接内存就完成了。

如何避免这种情况?可能会说MappedBuffer来隐式处置或使用某种类型的MappedBuffer池

EN

回答 4

Stack Overflow用户

发布于 2011-12-19 06:10:20

您可以通过直接清理映射的字节缓冲区来避免触发GC。

代码语言:javascript
运行
复制
public static void clean(ByteBuffer bb) {
    if(bb == null) return;
    Cleaner cleaner = ((DirectBuffer) bb).cleaner();
    if(cleaner != null) cleaner.clean();
}

如果您在丢弃之前调用此函数,则不会耗尽虚拟内存。

也许您可以考虑创建更大的ByteBuffers (除非您有大量的文件)创建MappedByteBuffer是不免费的(在某些机器上需要大约50微秒)

票数 6
EN

Stack Overflow用户

发布于 2011-12-19 01:03:42

错误消息显示"map failed",而不是"heap space“或"permgen space”。这意味着JVM没有足够的地址空间可用。

请参阅Sun数据库中的this bug,以及this question

第一个链接提供了一个变通方法(ewww),它接近于第二个链接所说的内容:

代码语言:javascript
运行
复制
    try {
        buffer = channel.map(READ_ONLY, ofs, n);
    } catch (java.io.IOException e) {
        System.gc();
        System.runFinalization();
        buffer = channel.map(READ_ONLY, ofs, n);
    }
票数 3
EN

Stack Overflow用户

发布于 2011-12-19 00:47:09

也许将这些MappedBuffers放入池中的WeakHashMap会起作用。

但在你猜测根本原因之前,我建议将你的应用程序连接到Visual VM 1.3.3,并安装所有的插件,这样你就可以确切地看到是什么导致了面向对象模型错误。你假设这些MappedBuffers正在做这件事,但是它们只有5-6个线程,每个线程只有5MB -总共25-30MB。

有数据比猜测更好。Visual VM将为您获取它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8553158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档