1 /* 2 * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.nio; 27 28 import java.io.FileDescriptor; 29 import java.lang.ref.Reference; 30 import java.util.Objects; 31 32 import jdk.internal.access.foreign.MemorySegmentProxy; 33 import jdk.internal.misc.Unsafe; 34 35 36 /** 37 * A direct byte buffer whose content is a memory-mapped region of a file. 38 * 39 * <p> Mapped byte buffers are created via the {@link 40 * java.nio.channels.FileChannel#map FileChannel.map} method. This class 41 * extends the {@link ByteBuffer} class with operations that are specific to 42 * memory-mapped file regions. 43 * 44 * <p> A mapped byte buffer and the file mapping that it represents remain 45 * valid until the buffer itself is garbage-collected. 46 * 47 * <p> The content of a mapped byte buffer can change at any time, for example 48 * if the content of the corresponding region of the mapped file is changed by 49 * this program or another. Whether or not such changes occur, and when they 50 * occur, is operating-system dependent and therefore unspecified. 51 * 52 * <a id="inaccess"></a><p> All or part of a mapped byte buffer may become 53 * inaccessible at any time, for example if the mapped file is truncated. An 54 * attempt to access an inaccessible region of a mapped byte buffer will not 55 * change the buffer's content and will cause an unspecified exception to be 56 * thrown either at the time of the access or at some later time. It is 57 * therefore strongly recommended that appropriate precautions be taken to 58 * avoid the manipulation of a mapped file by this program, or by a 59 * concurrently running program, except to read or write the file's content. 60 * 61 * <p> Mapped byte buffers otherwise behave no differently than ordinary direct 62 * byte buffers. </p> 63 * 64 * 65 * @author Mark Reinhold 66 * @author JSR-51 Expert Group 67 * @since 1.4 68 */ 69 70 public abstract class MappedByteBuffer 71 extends ByteBuffer 72 { 73 74 // This is a little bit backwards: By rights MappedByteBuffer should be a 75 // subclass of DirectByteBuffer, but to keep the spec clear and simple, and 76 // for optimization purposes, it's easier to do it the other way around. 77 // This works because DirectByteBuffer is a package-private class. 78 79 // For mapped buffers, a FileDescriptor that may be used for mapping 80 // operations if valid; null if the buffer is not mapped. 81 private final FileDescriptor fd; 82 83 // A flag true if this buffer is mapped against non-volatile 84 // memory using one of the extended FileChannel.MapMode modes, 85 // MapMode.READ_ONLY_SYNC or MapMode.READ_WRITE_SYNC and false if 86 // it is mapped using any of the other modes. This flag only 87 // determines the behavior of force operations. 88 private final boolean isSync; 89 90 // This should only be invoked by the DirectByteBuffer constructors 91 // 92 MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private 93 FileDescriptor fd, boolean isSync, MemorySegmentProxy segment) { 94 super(mark, pos, lim, cap, segment); 95 this.fd = fd; 96 this.isSync = isSync; 97 } 98 99 MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private 100 boolean isSync, MemorySegmentProxy segment) { 101 super(mark, pos, lim, cap, segment); 102 this.fd = null; 103 this.isSync = isSync; 104 } 105 106 MappedByteBuffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) { // package-private 107 super(mark, pos, lim, cap, segment); 108 this.fd = null; 109 this.isSync = false; 110 } 111 112 // Returns the distance (in bytes) of the buffer start from the 113 // largest page aligned address of the mapping less than or equal 114 // to the start address. 115 private long mappingOffset() { 116 return mappingOffset(0); 117 } 118 119 // Returns the distance (in bytes) of the buffer element 120 // identified by index from the largest page aligned address of 121 // the mapping less than or equal to the element address. Computed 122 // each time to avoid storing in every direct buffer. 123 private long mappingOffset(int index) { 124 int ps = Bits.pageSize(); 125 long indexAddress = address + index; 126 long baseAddress = alignDown(indexAddress, ps); 127 return indexAddress - baseAddress; 128 } 129 130 // Given an offset previously obtained from calling 131 // mappingOffset() returns the largest page aligned address of the 132 // mapping less than or equal to the buffer start address. 133 private long mappingAddress(long mappingOffset) { 134 return mappingAddress(mappingOffset, 0); 135 } 136 137 // Given an offset previously otained from calling 138 // mappingOffset(index) returns the largest page aligned address 139 // of the mapping less than or equal to the address of the buffer 140 // element identified by index. 141 private long mappingAddress(long mappingOffset, long index) { 142 long indexAddress = address + index; 143 return indexAddress - mappingOffset; 144 } 145 146 // given a mappingOffset previously otained from calling 147 // mappingOffset() return that offset added to the buffer 148 // capacity. 149 private long mappingLength(long mappingOffset) { 150 return mappingLength(mappingOffset, (long)capacity()); 151 } 152 153 // given a mappingOffset previously otained from calling 154 // mappingOffset(index) return that offset added to the supplied 155 // length. 156 private long mappingLength(long mappingOffset, long length) { 157 return length + mappingOffset; 158 } 159 160 // align address down to page size 161 private static long alignDown(long address, int pageSize) { 162 // pageSize must be a power of 2 163 return address & ~(pageSize - 1); 164 } 165 166 /** 167 * Tells whether this buffer was mapped against a non-volatile 168 * memory device by passing one of the sync map modes {@link 169 * jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC 170 * ExtendedMapModeMapMode#READ_ONLY_SYNC} or {@link 171 * jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC 172 * ExtendedMapMode#READ_WRITE_SYNC} in the call to {@link 173 * java.nio.channels.FileChannel#map FileChannel.map} or was 174 * mapped by passing one of the other map modes. 175 * 176 * @return true if the file was mapped using one of the sync map 177 * modes, otherwise false. 178 */ 179 private boolean isSync() { 180 return isSync; 181 } 182 183 /** 184 * Tells whether or not this buffer's content is resident in physical 185 * memory. 186 * 187 * <p> A return value of {@code true} implies that it is highly likely 188 * that all of the data in this buffer is resident in physical memory and 189 * may therefore be accessed without incurring any virtual-memory page 190 * faults or I/O operations. A return value of {@code false} does not 191 * necessarily imply that the buffer's content is not resident in physical 192 * memory. 193 * 194 * <p> The returned value is a hint, rather than a guarantee, because the 195 * underlying operating system may have paged out some of the buffer's data 196 * by the time that an invocation of this method returns. </p> 197 * 198 * @return {@code true} if it is likely that this buffer's content 199 * is resident in physical memory 200 */ 201 public final boolean isLoaded() { 202 if (fd == null) { 203 return true; 204 } 205 // a sync mapped buffer is always loaded 206 if (isSync()) { 207 return true; 208 } 209 if ((address == 0) || (capacity() == 0)) 210 return true; 211 long offset = mappingOffset(); 212 long length = mappingLength(offset); 213 return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length)); 214 } 215 216 // not used, but a potential target for a store, see load() for details. 217 private static byte unused; 218 219 /** 220 * Loads this buffer's content into physical memory. 221 * 222 * <p> This method makes a best effort to ensure that, when it returns, 223 * this buffer's content is resident in physical memory. Invoking this 224 * method may cause some number of page faults and I/O operations to 225 * occur. </p> 226 * 227 * @return This buffer 228 */ 229 public final MappedByteBuffer load() { 230 if (fd == null) { 231 return this; 232 } 233 // no need to load a sync mapped buffer 234 if (isSync()) { 235 return this; 236 } 237 if ((address == 0) || (capacity() == 0)) 238 return this; 239 long offset = mappingOffset(); 240 long length = mappingLength(offset); 241 load0(mappingAddress(offset), length); 242 243 // Read a byte from each page to bring it into memory. A checksum 244 // is computed as we go along to prevent the compiler from otherwise 245 // considering the loop as dead code. 246 Unsafe unsafe = Unsafe.getUnsafe(); 247 int ps = Bits.pageSize(); 248 int count = Bits.pageCount(length); 249 long a = mappingAddress(offset); 250 byte x = 0; 251 try { 252 for (int i=0; i<count; i++) { 253 // TODO consider changing to getByteOpaque thus avoiding 254 // dead code elimination and the need to calculate a checksum 255 x ^= unsafe.getByte(a); 256 a += ps; 257 } 258 } finally { 259 Reference.reachabilityFence(this); 260 } 261 if (unused != 0) 262 unused = x; 263 264 return this; 265 } 266 267 /** 268 * Forces any changes made to this buffer's content to be written to the 269 * storage device containing the mapped file. 270 * 271 * <p> If the file mapped into this buffer resides on a local storage 272 * device then when this method returns it is guaranteed that all changes 273 * made to the buffer since it was created, or since this method was last 274 * invoked, will have been written to that device. 275 * 276 * <p> If the file does not reside on a local device then no such guarantee 277 * is made. 278 * 279 * <p> If this buffer was not mapped in read/write mode ({@link 280 * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then 281 * invoking this method may have no effect. In particular, the 282 * method has no effect for buffers mapped in read-only or private 283 * mapping modes. This method may or may not have an effect for 284 * implementation-specific mapping modes. </p> 285 * 286 * @return This buffer 287 */ 288 public final MappedByteBuffer force() { 289 if (fd == null) { 290 return this; 291 } 292 if (isSync) { 293 return force(0, limit()); 294 } 295 if ((address != 0) && (capacity() != 0)) { 296 long offset = mappingOffset(); 297 force0(fd, mappingAddress(offset), mappingLength(offset)); 298 } 299 return this; 300 } 301 302 /** 303 * Forces any changes made to a region of this buffer's content to 304 * be written to the storage device containing the mapped 305 * file. The region starts at the given {@code index} in this 306 * buffer and is {@code length} bytes. 307 * 308 * <p> If the file mapped into this buffer resides on a local 309 * storage device then when this method returns it is guaranteed 310 * that all changes made to the selected region buffer since it 311 * was created, or since this method was last invoked, will have 312 * been written to that device. The force operation is free to 313 * write bytes that lie outside the specified region, for example 314 * to ensure that data blocks of some device-specific granularity 315 * are transferred in their entirety. 316 * 317 * <p> If the file does not reside on a local device then no such 318 * guarantee is made. 319 * 320 * <p> If this buffer was not mapped in read/write mode ({@link 321 * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then 322 * invoking this method may have no effect. In particular, the 323 * method has no effect for buffers mapped in read-only or private 324 * mapping modes. This method may or may not have an effect for 325 * implementation-specific mapping modes. </p> 326 * 327 * @param index 328 * The index of the first byte in the buffer region that is 329 * to be written back to storage; must be non-negative 330 * and less than limit() 331 * 332 * @param length 333 * The length of the region in bytes; must be non-negative 334 * and no larger than limit() - index 335 * 336 * @throws IndexOutOfBoundsException 337 * if the preconditions on the index and length do not 338 * hold. 339 * 340 * @return This buffer 341 * 342 * @since 13 343 */ 344 public final MappedByteBuffer force(int index, int length) { 345 if (fd == null) { 346 return this; 347 } 348 if ((address != 0) && (limit() != 0)) { 349 // check inputs 350 Objects.checkFromIndexSize(index, length, limit()); 351 if (isSync) { 352 // simply force writeback of associated cache lines 353 Unsafe.getUnsafe().writebackMemory(address + index, length); 354 } else { 355 // force writeback via file descriptor 356 long offset = mappingOffset(index); 357 force0(fd, mappingAddress(offset, index), mappingLength(offset, length)); 358 } 359 } 360 return this; 361 } 362 363 private native boolean isLoaded0(long address, long length, int pageCount); 364 private native void load0(long address, long length); 365 private native void force0(FileDescriptor fd, long address, long length); 366 367 // -- Covariant return type overrides 368 369 /** 370 * {@inheritDoc} 371 */ 372 @Override 373 public final MappedByteBuffer position(int newPosition) { 374 super.position(newPosition); 375 return this; 376 } 377 378 /** 379 * {@inheritDoc} 380 */ 381 @Override 382 public final MappedByteBuffer limit(int newLimit) { 383 super.limit(newLimit); 384 return this; 385 } 386 387 /** 388 * {@inheritDoc} 389 */ 390 @Override 391 public final MappedByteBuffer mark() { 392 super.mark(); 393 return this; 394 } 395 396 /** 397 * {@inheritDoc} 398 */ 399 @Override 400 public final MappedByteBuffer reset() { 401 super.reset(); 402 return this; 403 } 404 405 /** 406 * {@inheritDoc} 407 */ 408 @Override 409 public final MappedByteBuffer clear() { 410 super.clear(); 411 return this; 412 } 413 414 /** 415 * {@inheritDoc} 416 */ 417 @Override 418 public final MappedByteBuffer flip() { 419 super.flip(); 420 return this; 421 } 422 423 /** 424 * {@inheritDoc} 425 */ 426 @Override 427 public final MappedByteBuffer rewind() { 428 super.rewind(); 429 return this; 430 } 431 }