JDK-6417205 : (fc) Out of address space because mapped ByteBuffers are not freed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 1.4.2_05,5.0u16,6
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,solaris_10
  • CPU: generic,sparc
  • Submitted: 2006-04-24
  • Updated: 2012-01-11
  • Resolved: 2006-05-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b86Fixed
Related Reports
Duplicate :  
Relates :  
Description
When memory mapping a file, it is possible to run out of address space in 32-bit VM. This happens even if the file is mapped in smallish chunks and those ByteBuffers are no longer reachable. The reason is that GC never kicks in to free the buffers:

===
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import static java.nio.channels.FileChannel.MapMode.READ_ONLY;

public class Test {
    
    public static void main(String[] args) throws Exception {
        String name = args[0];
        FileChannel channel = new RandomAccessFile(name, "r").getChannel();
        long size = channel.size();
        System.out.println("File " + name + " is " + size + " bytes large");
        long ofs = 0;
        int chunksize = 512 * 1024 * 1024;
        while (ofs < size) {
            int n = (int)Math.min(chunksize, size - ofs);
            ByteBuffer buffer = channel.map(READ_ONLY, ofs, n);
            System.out.println("Mapped " + n + " bytes at offset " + ofs);
            ofs += n;
        }
        channel.close();
    }
}
===

java -showversion -verbose:gc Test large.iso
java version "1.6.0-beta2"
Java(TM) SE Runtime Environment (build 1.6.0-beta2-b81)
Java HotSpot(TM) Client VM (build 1.6.0-beta2-b81, mixed mode)

File large.iso is 6603407360 bytes large
Mapped 536870912 bytes at offset 0
Mapped 536870912 bytes at offset 536870912
Mapped 536870912 bytes at offset 1073741824
Mapped 536870912 bytes at offset 1610612736
Mapped 536870912 bytes at offset 2147483648
Mapped 536870912 bytes at offset 2684354560
Mapped 536870912 bytes at offset 3221225472
Exception in thread "main" java.io.IOException: Not enough space
        at sun.nio.ch.FileChannelImpl.map0(Native Method)
        at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:742)
        at Test.main(Test.java:18)

Comments
EVALUATION Rather than simply forcing gc any time the map fails with an IOExcepion, we look for the instances in the native call's return value where the failure was due to lack of memory (e.g. ENOMEM), throw an OutOfMemoryError and retry only for those cases. If we fail again, we give up and throw the expected IOException.
23-05-2006

EVALUATION Reasonable solution to help with resource issues that can arise when mapped byte buffers aren't unmapped in a timely manner.
24-04-2006

WORK AROUND ByteBuffer buffer; try { buffer = channel.map(READ_ONLY, ofs, n); } catch (java.io.IOException e) { System.gc(); System.runFinalization(); buffer = channel.map(READ_ONLY, ofs, n); } *** (#1 of 1): [ UNSAVED ] ###@###.###
24-04-2006

SUGGESTED FIX sun.nio.ch.FileChannelImpl.map() should call System.gc() if the native map0() call fails, similar to what java.nio.Bits.reserveMemory() does.
24-04-2006