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