1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.nio;
28 
29 import dalvik.annotation.codegen.CovariantReturnType;
30 
31 import java.io.FileDescriptor;
32 import java.io.UncheckedIOException;
33 import java.lang.ref.Reference;
34 import java.util.Objects;
35 
36 import jdk.internal.misc.Unsafe;
37 
38 
39 /**
40  * A direct byte buffer whose content is a memory-mapped region of a file.
41  *
42  * <p> Mapped byte buffers are created via the {@link
43  * java.nio.channels.FileChannel#map FileChannel.map} method.  This class
44  * extends the {@link ByteBuffer} class with operations that are specific to
45  * memory-mapped file regions.
46  *
47  * <p> A mapped byte buffer and the file mapping that it represents remain
48  * valid until the buffer itself is garbage-collected.
49  *
50  * <p> The content of a mapped byte buffer can change at any time, for example
51  * if the content of the corresponding region of the mapped file is changed by
52  * this program or another.  Whether or not such changes occur, and when they
53  * occur, is operating-system dependent and therefore unspecified.
54  *
55  * <a id="inaccess"></a><p> All or part of a mapped byte buffer may become
56  * inaccessible at any time, for example if the mapped file is truncated.  An
57  * attempt to access an inaccessible region of a mapped byte buffer will not
58  * change the buffer's content and will cause an unspecified exception to be
59  * thrown either at the time of the access or at some later time.  It is
60  * therefore strongly recommended that appropriate precautions be taken to
61  * avoid the manipulation of a mapped file by this program, or by a
62  * concurrently running program, except to read or write the file's content.
63  *
64  * <p> Mapped byte buffers otherwise behave no differently than ordinary direct
65  * byte buffers. </p>
66  *
67  *
68  * @author Mark Reinhold
69  * @author JSR-51 Expert Group
70  * @since 1.4
71  */
72 
73 public abstract class MappedByteBuffer
74     extends ByteBuffer
75 {
76 
77     // This is a little bit backwards: By rights MappedByteBuffer should be a
78     // subclass of DirectByteBuffer, but to keep the spec clear and simple, and
79     // for optimization purposes, it's easier to do it the other way around.
80     // This works because DirectByteBuffer is a package-private class.
81 
82     // For mapped buffers, a FileDescriptor that may be used for mapping
83     // operations if valid; null if the buffer is not mapped.
84     private final FileDescriptor fd;
85 
86     // A flag true if this buffer is mapped against non-volatile
87     // memory using one of the extended FileChannel.MapMode modes,
88     // MapMode.READ_ONLY_SYNC or MapMode.READ_WRITE_SYNC and false if
89     // it is mapped using any of the other modes. This flag only
90     // determines the behavior of force operations.
91     private final boolean isSync;
92 
93     // Android-removed: Remove unsupported scoped memory access.
94     // static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
95 
96     // This should only be invoked by the DirectByteBuffer constructors
97     //
98     // Android-removed: Removed MemorySegmentProxy to be supported yet./
MappedByteBuffer(int mark, int pos, int lim, int cap, FileDescriptor fd, boolean isSync)99     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
100                      FileDescriptor fd, boolean isSync) {
101         super(mark, pos, lim, cap);
102         this.fd = fd;
103         this.isSync = isSync;
104     }
105 
106     // Android-added: Additional constructor for use by Android's DirectByteBuffer.
MappedByteBuffer(int mark, int pos, int lim, int cap, byte[] buf, int offset)107     MappedByteBuffer(int mark, int pos, int lim, int cap, byte[] buf, int offset) {
108         super(mark, pos, lim, cap, buf, offset);
109         this.fd = null;
110         isSync = false;
111     }
112 
113     // Android-removed: Removed MemorySegmentProxy to be supported yet./
MappedByteBuffer(int mark, int pos, int lim, int cap, boolean isSync)114     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
115                      boolean isSync) {
116         super(mark, pos, lim, cap);
117         this.fd = null;
118         this.isSync = isSync;
119     }
120 
121     // Android-removed: Removed MemorySegmentProxy to be supported yet.
MappedByteBuffer(int mark, int pos, int lim, int cap)122     MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
123         super(mark, pos, lim, cap);
124         this.fd = null;
125         this.isSync = false;
126     }
127 
128     // Android-removed: Remove unsupported UnmapperProxy.
129     /*
130     UnmapperProxy unmapper() {
131         return fd != null ?
132                 new UnmapperProxy() {
133                     @Override
134                     public long address() {
135                         return address;
136                     }
137 
138                     @Override
139                     public FileDescriptor fileDescriptor() {
140                         return fd;
141                     }
142 
143                     @Override
144                     public boolean isSync() {
145                         return isSync;
146                     }
147 
148                     @Override
149                     public void unmap() {
150                         Unsafe.getUnsafe().invokeCleaner(MappedByteBuffer.this);
151                     }
152                 } : null;
153     }
154     */
155 
156     /**
157      * Tells whether this buffer was mapped against a non-volatile
158      * memory device by passing one of the sync map modes {@link
159      * jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC
160      * ExtendedMapModeMapMode#READ_ONLY_SYNC} or {@link
161      * jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC
162      * ExtendedMapMode#READ_WRITE_SYNC} in the call to {@link
163      * java.nio.channels.FileChannel#map FileChannel.map} or was
164      * mapped by passing one of the other map modes.
165      *
166      * @return true if the file was mapped using one of the sync map
167      * modes, otherwise false.
168      */
isSync()169     final boolean isSync() { // package-private
170         return isSync;
171     }
172 
173     /**
174      * Returns the {@code FileDescriptor} associated with this
175      * {@code MappedByteBuffer}.
176      *
177      * @return the buffer's file descriptor; may be {@code null}
178      */
fileDescriptor()179     final FileDescriptor fileDescriptor() { // package-private
180         return fd;
181     }
182 
183     // Android-added: Added the unused field to avoid compiler optimization in load();
184     private static byte unused;
185     // Android-added: Added checkMapped as Android doesn't allow null fd in DirectByteBuffer.
checkMapped()186     private void checkMapped() {
187         if (fd == null)
188             // Can only happen if a user explicitly casts a direct byte buffer
189             throw new UnsupportedOperationException();
190     }
191 
192     // BEGIN Android-added: Additional fields / methods for removing unsupported scoped memory.
193     // Returns the distance (in bytes) of the buffer from the page aligned address
194     // of the mapping. Computed each time to avoid storing in every direct buffer.
mappingOffset()195     private long mappingOffset() {
196         return mappingOffset(address);
197     }
198 
mappingOffset(long addr)199     private static long mappingOffset(long addr) {
200         int ps = Bits.pageSize();
201         long offset = addr % ps;
202         return (offset >= 0) ? offset : (ps + offset);
203     }
204 
mappingAddress(long mappingOffset)205     private long mappingAddress(long mappingOffset) {
206         return address - mappingOffset;
207     }
208 
mappingAddress(long addr, long mappingOffset)209     private static long mappingAddress(long addr, long mappingOffset) {
210         return addr - mappingOffset;
211     }
212 
mappingLength(long mappingOffset)213     private long mappingLength(long mappingOffset) {
214         return mappingLength(capacity(), mappingOffset);
215     }
216 
mappingLength(long length, long mappingOffset)217     private long mappingLength(long length, long mappingOffset) {
218         return length + mappingOffset;
219     }
220     // END Android-added: Additional fields / methods for removing unsupported scoped memory.
221 
222 
223     /**
224      * Tells whether or not this buffer's content is resident in physical
225      * memory.
226      *
227      * <p> A return value of {@code true} implies that it is highly likely
228      * that all of the data in this buffer is resident in physical memory and
229      * may therefore be accessed without incurring any virtual-memory page
230      * faults or I/O operations.  A return value of {@code false} does not
231      * necessarily imply that the buffer's content is not resident in physical
232      * memory.
233      *
234      * <p> The returned value is a hint, rather than a guarantee, because the
235      * underlying operating system may have paged out some of the buffer's data
236      * by the time that an invocation of this method returns.  </p>
237      *
238      * @return  {@code true} if it is likely that this buffer's content
239      *          is resident in physical memory
240      */
isLoaded()241     public final boolean isLoaded() {
242         // Android-added: Android throws UOE for memory-backed direct byte buffer.
243         // if (fd == null) {
244         //     return true;
245         // }
246         checkMapped();
247         // Android-changed: Remove unsupported scoped memory access.
248         // return SCOPED_MEMORY_ACCESS.isLoaded(scope(), address, isSync, capacity());
249         if ((address == 0) || (capacity() == 0))
250             return true;
251         long offset = mappingOffset();
252         long length = mappingLength(offset);
253         return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length));
254     }
255 
256     /**
257      * Loads this buffer's content into physical memory.
258      *
259      * <p> This method makes a best effort to ensure that, when it returns,
260      * this buffer's content is resident in physical memory.  Invoking this
261      * method may cause some number of page faults and I/O operations to
262      * occur. </p>
263      *
264      * @return  This buffer
265      */
load()266     public final MappedByteBuffer load() {
267         // Android-added: Android throws UOE for memory-backed direct byte buffer.
268         // if (fd == null) {
269         //     return this;
270         // }
271         checkMapped();
272         // Android-changed: Remove unsupported scoped memory access.
273         /*
274         try {
275             SCOPED_MEMORY_ACCESS.load(scope(), address, isSync, capacity());
276         } finally {
277             Reference.reachabilityFence(this);
278         }
279         */
280         if ((address == 0) || (capacity() == 0))
281             return this;
282         long offset = mappingOffset();
283         long length = mappingLength(offset);
284         load0(mappingAddress(offset), length);
285 
286         // Read a byte from each page to bring it into memory. A checksum
287         // is computed as we go along to prevent the compiler from otherwise
288         // considering the loop as dead code.
289         Unsafe unsafe = Unsafe.getUnsafe();
290         int ps = Bits.pageSize();
291         long count = Bits.pageCount(length);
292         long a = mappingAddress(offset);
293         byte x = 0;
294         for (int i=0; i<count; i++) {
295             x ^= unsafe.getByte(a);
296             a += ps;
297         }
298         if (unused != 0)
299             unused = x;
300 
301         return this;
302     }
303 
304     /**
305      * Forces any changes made to this buffer's content to be written to the
306      * storage device containing the mapped file.  The region starts at index
307      * zero in this buffer and is {@code capacity()} bytes.
308      *
309      * <p> If the file mapped into this buffer resides on a local storage
310      * device then when this method returns it is guaranteed that all changes
311      * made to the buffer since it was created, or since this method was last
312      * invoked, will have been written to that device.
313      *
314      * <p> If the file does not reside on a local device then no such guarantee
315      * is made.
316      *
317      * <p> If this buffer was not mapped in read/write mode ({@link
318      * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then
319      * invoking this method may have no effect. In particular, the
320      * method has no effect for buffers mapped in read-only or private
321      * mapping modes. This method may or may not have an effect for
322      * implementation-specific mapping modes. </p>
323      *
324      * @throws UncheckedIOException
325      *         If an I/O error occurs writing the buffer's content to the
326      *         storage device containing the mapped file
327      *
328      * @return  This buffer
329      */
force()330     public final MappedByteBuffer force() {
331         // Android-changed:: Android throws UOE for memory-backed direct byte buffer.
332         // if (fd == null) {
333         //     return this;
334         // }
335         checkMapped();
336         int capacity = capacity();
337         if (isSync || ((address != 0) && (capacity != 0))) {
338             return force(0, capacity);
339         }
340         return this;
341     }
342 
343     /**
344      * Forces any changes made to a region of this buffer's content to
345      * be written to the storage device containing the mapped
346      * file. The region starts at the given {@code index} in this
347      * buffer and is {@code length} bytes.
348      *
349      * <p> If the file mapped into this buffer resides on a local
350      * storage device then when this method returns it is guaranteed
351      * that all changes made to the selected region buffer since it
352      * was created, or since this method was last invoked, will have
353      * been written to that device. The force operation is free to
354      * write bytes that lie outside the specified region, for example
355      * to ensure that data blocks of some device-specific granularity
356      * are transferred in their entirety.
357      *
358      * <p> If the file does not reside on a local device then no such
359      * guarantee is made.
360      *
361      * <p> If this buffer was not mapped in read/write mode ({@link
362      * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then
363      * invoking this method may have no effect. In particular, the
364      * method has no effect for buffers mapped in read-only or private
365      * mapping modes. This method may or may not have an effect for
366      * implementation-specific mapping modes. </p>
367      *
368      * @param  index
369      *         The index of the first byte in the buffer region that is
370      *         to be written back to storage; must be non-negative
371      *         and less than {@code capacity()}
372      *
373      * @param  length
374      *         The length of the region in bytes; must be non-negative
375      *         and no larger than {@code capacity() - index}
376      *
377      * @throws IndexOutOfBoundsException
378      *         if the preconditions on the index and length do not
379      *         hold.
380      *
381      * @throws UncheckedIOException
382      *         If an I/O error occurs writing the buffer's content to the
383      *         storage device containing the mapped file
384      *
385      * @return  This buffer
386      *
387      * @since 13
388      */
force(int index, int length)389     public final MappedByteBuffer force(int index, int length) {
390         // Android-note: Android doesn't throw UOE, because new API doesn't need forward compat.
391         if (fd == null) {
392             return this;
393         }
394         int capacity = capacity();
395         if ((address != 0) && (capacity != 0)) {
396             // check inputs
397             Objects.checkFromIndexSize(index, length, capacity);
398             // Android-changed: Remove unsupported scoped memory access.
399             // SCOPED_MEMORY_ACCESS.force(scope(), fd, address, isSync, index, length);
400             long firstByteAddress = address + index;
401             long offset = mappingOffset(firstByteAddress);
402             force0(fd, mappingAddress(firstByteAddress, offset), mappingLength(length, offset));
403         }
404         return this;
405     }
406 
407     // -- Covariant return type overrides
408 
409     /**
410      * {@inheritDoc}
411      */
412     // Android-changed: covariant overloads of *Buffer methods that return this.
413     @CovariantReturnType(returnType = ByteBuffer.class, presentAfter = 34)
414     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
415     @Override
position(int newPosition)416     public final Buffer position(int newPosition) {
417         super.position(newPosition);
418         return this;
419     }
420 
421     /**
422      * {@inheritDoc}
423      */
424     // Android-changed: covariant overloads of *Buffer methods that return this.
425     @CovariantReturnType(returnType = ByteBuffer.class, presentAfter = 34)
426     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
427     @Override
limit(int newLimit)428     public final Buffer limit(int newLimit) {
429         super.limit(newLimit);
430         return this;
431     }
432 
433     /**
434      * {@inheritDoc}
435      */
436     // Android-changed: covariant overloads of *Buffer methods that return this.
437     @CovariantReturnType(returnType = ByteBuffer.class, presentAfter = 34)
438     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
439     @Override
mark()440     public final Buffer mark() {
441         super.mark();
442         return this;
443     }
444 
445     /**
446      * {@inheritDoc}
447      */
448     // Android-changed: covariant overloads of *Buffer methods that return this.
449     @CovariantReturnType(returnType = ByteBuffer.class, presentAfter = 34)
450     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
451     @Override
reset()452     public final Buffer reset() {
453         super.reset();
454         return this;
455     }
456 
457     /**
458      * {@inheritDoc}
459      */
460     // Android-changed: covariant overloads of *Buffer methods that return this.
461     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
462     @CovariantReturnType(returnType = ByteBuffer.class, presentAfter = 34)
463     @Override
clear()464     public final Buffer clear() {
465         super.clear();
466         return this;
467     }
468 
469     /**
470      * {@inheritDoc}
471      */
472     // Android-changed: covariant overloads of *Buffer methods that return this.
473     @CovariantReturnType(returnType = ByteBuffer.class, presentAfter = 34)
474     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
475     @Override
flip()476     public final Buffer flip() {
477         super.flip();
478         return this;
479     }
480 
481     /**
482      * {@inheritDoc}
483      */
484     // Android-changed: covariant overloads of *Buffer methods that return this.
485     @CovariantReturnType(returnType = ByteBuffer.class, presentAfter = 34)
486     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
487     @Override
rewind()488     public final Buffer rewind() {
489         super.rewind();
490         return this;
491     }
492 
493     /**
494      * {@inheritDoc}
495      *
496      * <p> Reading bytes into physical memory by invoking {@code load()} on the
497      * returned buffer, or writing bytes to the storage device by invoking
498      * {@code force()} on the returned buffer, will only act on the sub-range
499      * of this buffer that the returned buffer represents, namely
500      * {@code [position(),limit())}.
501      */
502     // Android-changed: covariant overloads of *Buffer methods that return this.
503     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
504     @Override
slice()505     public abstract ByteBuffer slice();
506 
507     /**
508      * {@inheritDoc}
509      *
510      * <p> Reading bytes into physical memory by invoking {@code load()} on the
511      * returned buffer, or writing bytes to the storage device by invoking
512      * {@code force()} on the returned buffer, will only act on the sub-range
513      * of this buffer that the returned buffer represents, namely
514      * {@code [index,index+length)}, where {@code index} and {@code length} are
515      * assumed to satisfy the preconditions.
516      */
slice(int index, int length)517     public abstract MappedByteBuffer slice(int index, int length);
518 
isLoaded0(long address, long length, long pageCount)519     private native boolean isLoaded0(long address, long length, long pageCount);
load0(long address, long length)520     private native void load0(long address, long length);
force0(FileDescriptor fd, long address, long length)521     private native void force0(FileDescriptor fd, long address, long length);
522 
523 
524     /**
525      * {@inheritDoc}
526      */
527     // Android-changed: covariant overloads of *Buffer methods that return this.
528     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
529     @Override
duplicate()530     public abstract ByteBuffer duplicate();
531 
532     /**
533      * {@inheritDoc}
534      */
535     // Android-changed: covariant overloads of *Buffer methods that return this.
536     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
537     @Override
compact()538     public abstract ByteBuffer compact();
539 }
540