MemoryMappedFile.java revision bffb058e565a97f838247f1e092b0d17b26cb68e
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package libcore.io; 18 19import java.io.Closeable; 20import java.io.FileDescriptor; 21import java.io.IOException; 22import java.nio.ByteOrder; 23import java.nio.channels.FileChannel; 24import org.apache.harmony.luni.platform.OSMemory; 25import org.apache.harmony.nio.internal.FileChannelImpl; 26 27/** 28 * A memory-mapped file. Use {@link #mmap} to map a file, {@link #close} to unmap a file, 29 * and either {@link #bigEndianIterator} or {@link #littleEndianIterator} to get a seekable 30 * {@link BufferIterator} over the mapped data. 31 */ 32public final class MemoryMappedFile implements Closeable { 33 private int address; 34 35 // Until we have 64-bit address spaces, we only need an int for 'size'. 36 private final int size; 37 38 private MemoryMappedFile(int address, int size) { 39 this.address = address; 40 this.size = size; 41 } 42 43 public static MemoryMappedFile mmap(FileChannel fc, FileChannel.MapMode mapMode, long start, long size) throws IOException { 44 return mmap(((FileChannelImpl) fc).getHandle(), mapMode, start, size); 45 } 46 47 public static MemoryMappedFile mmap(FileDescriptor fd, FileChannel.MapMode mapMode, long start, long size) throws IOException { 48 return mmap(IoUtils.getFd(fd), mapMode, start, size); 49 } 50 51 private static MemoryMappedFile mmap(int fd, FileChannel.MapMode mapMode, long start, long size) throws IOException { 52 if (start < 0) { 53 throw new IllegalArgumentException("start < 0: " + start); 54 } 55 if (size <= 0) { 56 throw new IllegalArgumentException("size <= 0: " + size); 57 } 58 if ((start + size) > Integer.MAX_VALUE) { 59 throw new IllegalArgumentException("(start + size) > Integer.MAX_VALUE"); 60 } 61 int address = OSMemory.mmap(fd, start, size, mapMode); 62 return new MemoryMappedFile(address, (int) size); 63 } 64 65 /** 66 * Unmaps this memory-mapped file using munmap(2). This is a no-op if close has already been 67 * called. Note that this class does <i>not</i> use finalization; you must call {@code close} 68 * yourself. 69 * 70 * Calling this method invalidates any iterators over this {@code MemoryMappedFile}. It is an 71 * error to use such an iterator after calling {@code close}. 72 */ 73 public synchronized void close() throws IOException { 74 if (address != 0) { 75 OSMemory.munmap(address, size); 76 address = 0; 77 } 78 } 79 80 /** 81 * Returns a new iterator that treats the mapped data as big-endian. 82 */ 83 public BufferIterator bigEndianIterator() { 84 return new BufferIterator(address, size, ByteOrder.BIG_ENDIAN.needsSwap); 85 } 86 87 /** 88 * Returns a new iterator that treats the mapped data as little-endian. 89 */ 90 public BufferIterator littleEndianIterator() { 91 return new BufferIterator(address, size, ByteOrder.LITTLE_ENDIAN.needsSwap); 92 } 93 94 /** 95 * Returns the size in bytes of the memory-mapped region. 96 */ 97 public int size() { 98 return size; 99 } 100} 101