MappedByteBuffer.java revision c73a5be50cdd804ff3c12e7b43da08c33cdd6f21
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  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 java.nio;
18
19import java.nio.channels.FileChannel.MapMode;
20import org.apache.harmony.luni.platform.OSMemory;
21
22/**
23 * {@code MappedByteBuffer} is a special kind of direct byte buffer which maps a
24 * region of file to memory.
25 * <p>
26 * {@code MappedByteBuffer} can be created by calling
27 * {@link java.nio.channels.FileChannel#map(java.nio.channels.FileChannel.MapMode, long, long) FileChannel.map}.
28 * Once created, the mapping between the byte buffer and the file region remains
29 * valid until the byte buffer is garbage collected.
30 * <p>
31 * All or part of a {@code MappedByteBuffer}'s content may change or become
32 * inaccessible at any time, since the mapped file region can be modified by
33 * another thread or process at any time. If this happens, the behavior of the
34 * {@code MappedByteBuffer} is undefined.
35 */
36public abstract class MappedByteBuffer extends ByteBuffer {
37
38    final DirectByteBuffer wrapped;
39
40    private final MapMode mapMode;
41
42    MappedByteBuffer(ByteBuffer directBuffer) {
43        super(directBuffer.capacity);
44        if (!directBuffer.isDirect()) {
45            throw new IllegalArgumentException();
46        }
47        this.wrapped = (DirectByteBuffer) directBuffer;
48        this.mapMode = null;
49    }
50
51    MappedByteBuffer(PlatformAddress addr, int capacity, int offset, MapMode mapMode) {
52        super(capacity);
53        this.mapMode = mapMode;
54        if (mapMode == MapMode.READ_ONLY) {
55            wrapped = new ReadOnlyDirectByteBuffer(addr, capacity, offset);
56        } else {
57            wrapped = new ReadWriteDirectByteBuffer(addr, capacity, offset);
58        }
59    }
60
61    /**
62     * Indicates whether this buffer's content is loaded. If the result is true
63     * there is a high probability that the whole buffer memory is currently
64     * loaded in RAM. If it is false it is unsure if it is loaded or not.
65     *
66     * @return {@code true} if this buffer's content is loaded, {@code false}
67     *         otherwise.
68     */
69    public final boolean isLoaded() {
70        PlatformAddress address = ((DirectBuffer) wrapped).getBaseAddress();
71        return OSMemory.isLoaded(address.toInt(), address.getSize());
72    }
73
74    /**
75     * Loads this buffer's content into memory but it is not guaranteed to
76     * succeed.
77     *
78     * @return this buffer.
79     */
80    public final MappedByteBuffer load() {
81        PlatformAddress address = ((DirectBuffer) wrapped).getBaseAddress();
82        OSMemory.load(address.toInt(), address.getSize());
83        return this;
84    }
85
86    /**
87     * Writes all changes of the buffer to the mapped file. If the mapped file
88     * is stored on a local device, it is guaranteed that the changes are
89     * written to the file. No such guarantee is given if the file is located on
90     * a remote device.
91     *
92     * @return this buffer.
93     */
94    public final MappedByteBuffer force() {
95        if (mapMode == MapMode.READ_WRITE) {
96            PlatformAddress address = ((DirectBuffer) wrapped).getBaseAddress();
97            OSMemory.msync(address.toInt(), address.getSize());
98        }
99        return this;
100    }
101}
102