考虑创建 5-6 个线程的应用程序,每个线程在循环中为 5mb 页面大小分配 MappedByteBuffer。
MappedByteBuffer b = ch.map(FileChannel.MapMode.READ_ONLY, r, 1024*1024*5);
迟早,当应用程序处理大文件时,会抛出 oom
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-ed 太晚了,然后直接内存就完成了。
如何避免这种情况?可能会说 MappedBuffer 隐式处理或使用某种 MappedBuffer 池