United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6417205 (fc) Out of address space because mapped ByteBuffers are not freed
JDK-6417205 : (fc) Out of address space because mapped ByteBuffers are not freed

Details
Type:
Bug
Submit Date:
2006-04-24
Status:
Resolved
Updated Date:
2012-01-11
Project Name:
JDK
Resolved Date:
2006-05-30
Component:
core-libs
OS:
generic,solaris_10
Sub-Component:
java.nio
CPU:
sparc,generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
1.4.2_05,5.0u16,6
Fixed Versions:

Related Reports
Duplicate:
Relates:

Sub Tasks

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
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 ] ###@###.###
                                     
2006-04-24
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.
                                     
2006-04-24
EVALUATION

Reasonable solution to help with resource issues that can arise when mapped byte buffers aren't unmapped in a timely manner.
                                     
2006-04-24
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.
                                     
2006-05-23



Hardware and Software, Engineered to Work Together