使用java.nio.MappedByteBuffer时防止OutOfMemory [英] Prevent OutOfMemory when using java.nio.MappedByteBuffer

查看:1177
本文介绍了使用java.nio.MappedByteBuffer时防止OutOfMemory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Consider application, which create 5-6 threads, each thread in cycle allocate MappedByteBuffer for 5mb page size.

MappedByteBuffer b = ch.map(FileChannel.MapMode.READ_ONLY, r, 1024*1024*5);

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

Sooner or later, when application works with big files, oom is thrown

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-s的GC编辑太晚,后来直接内存完成。

According to specification, MappedBuffer should dispose direct memory as soon as it is GC itself. Looks like the problem is, that MappedBuffer-s are GC-ed too late, later then direct memory finished.

如何避免这种情况?可能会说MappedBuffer隐式处理或使用某种MappedBuffer池

How to avoid this situation ? Probably say MappedBuffer to dispose implicitly or use some kind of pool of MappedBuffer

推荐答案

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

You can avoid having to trigger a GC by cleaning up the mapped byte buffers directly.

public static void clean(ByteBuffer bb) {
    if(bb == null) return;
    Cleaner cleaner = ((DirectBuffer) bb).cleaner();
    if(cleaner != null) cleaner.clean();
}

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

Provided you call this before discarding, you won't run out of virtual memory.

也许您可以减少创建较大的ByteBuffers(除非您有大量文件)创建MappedByteBuffer不是免费的(大约需要50微秒)一些机器)

Perhaps you can look at creating larger ByteBuffers less often (unless you have a large number of files) Creating a MappedByteBuffer is not free (takes about 50 micro-seconds on some machines)

这篇关于使用java.nio.MappedByteBuffer时防止OutOfMemory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆