1 /*
2  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4  *
5  *
6  *
7  *
8  *
9  *
10  *
11  *
12  *
13  *
14  *
15  *
16  *
17  *
18  *
19  *
20  *
21  *
22  *
23  *
24  */

25
26 package java.nio;
27
28 import java.io.FileDescriptor;
29 import sun.misc.Unsafe;
30
31
32 /**
33  * A direct byte buffer whose content is a memory-mapped region of a file.
34  *
35  * <p> Mapped byte buffers are created via the {@link
36  * java.nio.channels.FileChannel#map FileChannel.map} method.  This class
37  * extends the {@link ByteBuffer} class with operations that are specific to
38  * memory-mapped file regions.
39  *
40  * <p> A mapped byte buffer and the file mapping that it represents remain
41  * valid until the buffer itself is garbage-collected.
42  *
43  * <p> The content of a mapped byte buffer can change at any time, for example
44  * if the content of the corresponding region of the mapped file is changed by
45  * this program or another.  Whether or not such changes occur, and when they
46  * occur, is operating-system dependent and therefore unspecified.
47  *
48  * <a name="inaccess"></a><p> All or part of a mapped byte buffer may become
49  * inaccessible at any time, for example if the mapped file is truncated.  An
50  * attempt to access an inaccessible region of a mapped byte buffer will not
51  * change the buffer's content and will cause an unspecified exception to be
52  * thrown either at the time of the access or at some later time.  It is
53  * therefore strongly recommended that appropriate precautions be taken to
54  * avoid the manipulation of a mapped file by this program, or by a
55  * concurrently running program, except to read or write the file's content.
56  *
57  * <p> Mapped byte buffers otherwise behave no differently than ordinary direct
58  * byte buffers. </p>
59  *
60  *
61  * @author Mark Reinhold
62  * @author JSR-51 Expert Group
63  * @since 1.4
64  */

65
66 public abstract class MappedByteBuffer
67     extends ByteBuffer
68 {
69
70     // This is a little bit backwards: By rights MappedByteBuffer should be a
71     // subclass of DirectByteBuffer, but to keep the spec clear and simple, and
72     // for optimization purposes, it's easier to do it the other way around.
73     // This works because DirectByteBuffer is a package-private class.
74
75     // For mapped buffers, a FileDescriptor that may be used for mapping
76     // operations if valid; null if the buffer is not mapped.
77     private final FileDescriptor fd;
78
79     // This should only be invoked by the DirectByteBuffer constructors
80     //
81     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
82                      FileDescriptor fd)
83     {
84         super(mark, pos, lim, cap);
85         this.fd = fd;
86     }
87
88     MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
89         super(mark, pos, lim, cap);
90         this.fd = null;
91     }
92
93     private void checkMapped() {
94         if (fd == null)
95             // Can only happen if a luser explicitly casts a direct byte buffer
96             throw new UnsupportedOperationException();
97     }
98
99     // Returns the distance (in bytes) of the buffer from the page aligned address
100     // of the mapping. Computed each time to avoid storing in every direct buffer.
101     private long mappingOffset() {
102         int ps = Bits.pageSize();
103         long offset = address % ps;
104         return (offset >= 0) ? offset : (ps + offset);
105     }
106
107     private long mappingAddress(long mappingOffset) {
108         return address - mappingOffset;
109     }
110
111     private long mappingLength(long mappingOffset) {
112         return (long)capacity() + mappingOffset;
113     }
114
115     /**
116      * Tells whether or not this buffer's content is resident in physical
117      * memory.
118      *
119      * <p> A return value of <tt>true</tt> implies that it is highly likely
120      * that all of the data in this buffer is resident in physical memory and
121      * may therefore be accessed without incurring any virtual-memory page
122      * faults or I/O operations.  A return value of <tt>false</tt> does not
123      * necessarily imply that the buffer's content is not resident in physical
124      * memory.
125      *
126      * <p> The returned value is a hint, rather than a guarantee, because the
127      * underlying operating system may have paged out some of the buffer's data
128      * by the time that an invocation of this method returns.  </p>
129      *
130      * @return  <tt>true</tt> if it is likely that this buffer's content
131      *          is resident in physical memory
132      */

133     public final boolean isLoaded() {
134         checkMapped();
135         if ((address == 0) || (capacity() == 0))
136             return true;
137         long offset = mappingOffset();
138         long length = mappingLength(offset);
139         return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length));
140     }
141
142     // not used, but a potential target for a store, see load() for details.
143     private static byte unused;
144
145     /**
146      * Loads this buffer's content into physical memory.
147      *
148      * <p> This method makes a best effort to ensure that, when it returns,
149      * this buffer's content is resident in physical memory.  Invoking this
150      * method may cause some number of page faults and I/O operations to
151      * occur. </p>
152      *
153      * @return  This buffer
154      */

155     public final MappedByteBuffer load() {
156         checkMapped();
157         if ((address == 0) || (capacity() == 0))
158             return this;
159         long offset = mappingOffset();
160         long length = mappingLength(offset);
161         load0(mappingAddress(offset), length);
162
163         // Read a byte from each page to bring it into memory. A checksum
164         // is computed as we go along to prevent the compiler from otherwise
165         // considering the loop as dead code.
166         Unsafe unsafe = Unsafe.getUnsafe();
167         int ps = Bits.pageSize();
168         int count = Bits.pageCount(length);
169         long a = mappingAddress(offset);
170         byte x = 0;
171         for (int i=0; i<count; i++) {
172             x ^= unsafe.getByte(a);
173             a += ps;
174         }
175         if (unused != 0)
176             unused = x;
177
178         return this;
179     }
180
181     /**
182      * Forces any changes made to this buffer's content to be written to the
183      * storage device containing the mapped file.
184      *
185      * <p> If the file mapped into this buffer resides on a local storage
186      * device then when this method returns it is guaranteed that all changes
187      * made to the buffer since it was created, or since this method was last
188      * invoked, will have been written to that device.
189      *
190      * <p> If the file does not reside on a local device then no such guarantee
191      * is made.
192      *
193      * <p> If this buffer was not mapped in read/write mode ({@link
194      * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then invoking this
195      * method has no effect. </p>
196      *
197      * @return  This buffer
198      */

199     public final MappedByteBuffer force() {
200         checkMapped();
201         if ((address != 0) && (capacity() != 0)) {
202             long offset = mappingOffset();
203             force0(fd, mappingAddress(offset), mappingLength(offset));
204         }
205         return this;
206     }
207
208     private native boolean isLoaded0(long address, long length, int pageCount);
209     private native void load0(long address, long length);
210     private native void force0(FileDescriptor fd, long address, long length);
211 }
212
Powered by JavaMelody