Path: blob/master/src/java.base/share/classes/java/nio/MappedByteBuffer.java
41152 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.nio;2627import java.io.FileDescriptor;28import java.io.UncheckedIOException;29import java.lang.ref.Reference;30import java.util.Objects;3132import jdk.internal.access.foreign.MemorySegmentProxy;33import jdk.internal.access.foreign.UnmapperProxy;34import jdk.internal.misc.ScopedMemoryAccess;35import jdk.internal.misc.Unsafe;363738/**39* A direct byte buffer whose content is a memory-mapped region of a file.40*41* <p> Mapped byte buffers are created via the {@link42* java.nio.channels.FileChannel#map FileChannel.map} method. This class43* extends the {@link ByteBuffer} class with operations that are specific to44* memory-mapped file regions.45*46* <p> A mapped byte buffer and the file mapping that it represents remain47* valid until the buffer itself is garbage-collected.48*49* <p> The content of a mapped byte buffer can change at any time, for example50* if the content of the corresponding region of the mapped file is changed by51* this program or another. Whether or not such changes occur, and when they52* occur, is operating-system dependent and therefore unspecified.53*54* <a id="inaccess"></a><p> All or part of a mapped byte buffer may become55* inaccessible at any time, for example if the mapped file is truncated. An56* attempt to access an inaccessible region of a mapped byte buffer will not57* change the buffer's content and will cause an unspecified exception to be58* thrown either at the time of the access or at some later time. It is59* therefore strongly recommended that appropriate precautions be taken to60* avoid the manipulation of a mapped file by this program, or by a61* concurrently running program, except to read or write the file's content.62*63* <p> Mapped byte buffers otherwise behave no differently than ordinary direct64* byte buffers. </p>65*66*67* @author Mark Reinhold68* @author JSR-51 Expert Group69* @since 1.470*/7172public abstract class MappedByteBuffer73extends ByteBuffer74{7576// This is a little bit backwards: By rights MappedByteBuffer should be a77// subclass of DirectByteBuffer, but to keep the spec clear and simple, and78// for optimization purposes, it's easier to do it the other way around.79// This works because DirectByteBuffer is a package-private class.8081// For mapped buffers, a FileDescriptor that may be used for mapping82// operations if valid; null if the buffer is not mapped.83private final FileDescriptor fd;8485// A flag true if this buffer is mapped against non-volatile86// memory using one of the extended FileChannel.MapMode modes,87// MapMode.READ_ONLY_SYNC or MapMode.READ_WRITE_SYNC and false if88// it is mapped using any of the other modes. This flag only89// determines the behavior of force operations.90private final boolean isSync;9192static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();9394// This should only be invoked by the DirectByteBuffer constructors95//96MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private97FileDescriptor fd, boolean isSync, MemorySegmentProxy segment) {98super(mark, pos, lim, cap, segment);99this.fd = fd;100this.isSync = isSync;101}102103MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private104boolean isSync, MemorySegmentProxy segment) {105super(mark, pos, lim, cap, segment);106this.fd = null;107this.isSync = isSync;108}109110MappedByteBuffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) { // package-private111super(mark, pos, lim, cap, segment);112this.fd = null;113this.isSync = false;114}115116UnmapperProxy unmapper() {117return fd != null ?118new UnmapperProxy() {119@Override120public long address() {121return address;122}123124@Override125public FileDescriptor fileDescriptor() {126return fd;127}128129@Override130public boolean isSync() {131return isSync;132}133134@Override135public void unmap() {136Unsafe.getUnsafe().invokeCleaner(MappedByteBuffer.this);137}138} : null;139}140141/**142* Tells whether this buffer was mapped against a non-volatile143* memory device by passing one of the sync map modes {@link144* jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC145* ExtendedMapModeMapMode#READ_ONLY_SYNC} or {@link146* jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC147* ExtendedMapMode#READ_WRITE_SYNC} in the call to {@link148* java.nio.channels.FileChannel#map FileChannel.map} or was149* mapped by passing one of the other map modes.150*151* @return true if the file was mapped using one of the sync map152* modes, otherwise false.153*/154final boolean isSync() { // package-private155return isSync;156}157158/**159* Returns the {@code FileDescriptor} associated with this160* {@code MappedByteBuffer}.161*162* @return the buffer's file descriptor; may be {@code null}163*/164final FileDescriptor fileDescriptor() { // package-private165return fd;166}167168/**169* Tells whether or not this buffer's content is resident in physical170* memory.171*172* <p> A return value of {@code true} implies that it is highly likely173* that all of the data in this buffer is resident in physical memory and174* may therefore be accessed without incurring any virtual-memory page175* faults or I/O operations. A return value of {@code false} does not176* necessarily imply that the buffer's content is not resident in physical177* memory.178*179* <p> The returned value is a hint, rather than a guarantee, because the180* underlying operating system may have paged out some of the buffer's data181* by the time that an invocation of this method returns. </p>182*183* @return {@code true} if it is likely that this buffer's content184* is resident in physical memory185*/186public final boolean isLoaded() {187if (fd == null) {188return true;189}190return SCOPED_MEMORY_ACCESS.isLoaded(scope(), address, isSync, capacity());191}192193/**194* Loads this buffer's content into physical memory.195*196* <p> This method makes a best effort to ensure that, when it returns,197* this buffer's content is resident in physical memory. Invoking this198* method may cause some number of page faults and I/O operations to199* occur. </p>200*201* @return This buffer202*/203public final MappedByteBuffer load() {204if (fd == null) {205return this;206}207try {208SCOPED_MEMORY_ACCESS.load(scope(), address, isSync, capacity());209} finally {210Reference.reachabilityFence(this);211}212return this;213}214215/**216* Forces any changes made to this buffer's content to be written to the217* storage device containing the mapped file. The region starts at index218* zero in this buffer and is {@code capacity()} bytes. An invocation of219* this method behaves in exactly the same way as the invocation220* {@link force(int,int) force(0,capacity())}.221*222* <p> If the file mapped into this buffer resides on a local storage223* device then when this method returns it is guaranteed that all changes224* made to the buffer since it was created, or since this method was last225* invoked, will have been written to that device.226*227* <p> If the file does not reside on a local device then no such guarantee228* is made.229*230* <p> If this buffer was not mapped in read/write mode ({@link231* java.nio.channels.FileChannel.MapMode#READ_WRITE}) then232* invoking this method may have no effect. In particular, the233* method has no effect for buffers mapped in read-only or private234* mapping modes. This method may or may not have an effect for235* implementation-specific mapping modes. </p>236*237* @throws UncheckedIOException238* If an I/O error occurs writing the buffer's content to the239* storage device containing the mapped file240*241* @return This buffer242*/243public final MappedByteBuffer force() {244if (fd == null) {245return this;246}247int capacity = capacity();248if (isSync || ((address != 0) && (capacity != 0))) {249return force(0, capacity);250}251return this;252}253254/**255* Forces any changes made to a region of this buffer's content to256* be written to the storage device containing the mapped257* file. The region starts at the given {@code index} in this258* buffer and is {@code length} bytes.259*260* <p> If the file mapped into this buffer resides on a local261* storage device then when this method returns it is guaranteed262* that all changes made to the selected region buffer since it263* was created, or since this method was last invoked, will have264* been written to that device. The force operation is free to265* write bytes that lie outside the specified region, for example266* to ensure that data blocks of some device-specific granularity267* are transferred in their entirety.268*269* <p> If the file does not reside on a local device then no such270* guarantee is made.271*272* <p> If this buffer was not mapped in read/write mode ({@link273* java.nio.channels.FileChannel.MapMode#READ_WRITE}) then274* invoking this method may have no effect. In particular, the275* method has no effect for buffers mapped in read-only or private276* mapping modes. This method may or may not have an effect for277* implementation-specific mapping modes. </p>278*279* @param index280* The index of the first byte in the buffer region that is281* to be written back to storage; must be non-negative282* and less than {@code capacity()}283*284* @param length285* The length of the region in bytes; must be non-negative286* and no larger than {@code capacity() - index}287*288* @throws IndexOutOfBoundsException289* if the preconditions on the index and length do not290* hold.291*292* @throws UncheckedIOException293* If an I/O error occurs writing the buffer's content to the294* storage device containing the mapped file295*296* @return This buffer297*298* @since 13299*/300public final MappedByteBuffer force(int index, int length) {301if (fd == null) {302return this;303}304int capacity = capacity();305if ((address != 0) && (capacity != 0)) {306// check inputs307Objects.checkFromIndexSize(index, length, capacity);308SCOPED_MEMORY_ACCESS.force(scope(), fd, address, isSync, index, length);309}310return this;311}312313// -- Covariant return type overrides314315/**316* {@inheritDoc}317*/318@Override319public final MappedByteBuffer position(int newPosition) {320super.position(newPosition);321return this;322}323324/**325* {@inheritDoc}326*/327@Override328public final MappedByteBuffer limit(int newLimit) {329super.limit(newLimit);330return this;331}332333/**334* {@inheritDoc}335*/336@Override337public final MappedByteBuffer mark() {338super.mark();339return this;340}341342/**343* {@inheritDoc}344*/345@Override346public final MappedByteBuffer reset() {347super.reset();348return this;349}350351/**352* {@inheritDoc}353*/354@Override355public final MappedByteBuffer clear() {356super.clear();357return this;358}359360/**361* {@inheritDoc}362*/363@Override364public final MappedByteBuffer flip() {365super.flip();366return this;367}368369/**370* {@inheritDoc}371*/372@Override373public final MappedByteBuffer rewind() {374super.rewind();375return this;376}377378/**379* {@inheritDoc}380*381* <p> Reading bytes into physical memory by invoking {@code load()} on the382* returned buffer, or writing bytes to the storage device by invoking383* {@code force()} on the returned buffer, will only act on the sub-range384* of this buffer that the returned buffer represents, namely385* {@code [position(),limit())}.386*/387@Override388public abstract MappedByteBuffer slice();389390/**391* {@inheritDoc}392*393* <p> Reading bytes into physical memory by invoking {@code load()} on the394* returned buffer, or writing bytes to the storage device by invoking395* {@code force()} on the returned buffer, will only act on the sub-range396* of this buffer that the returned buffer represents, namely397* {@code [index,index+length)}, where {@code index} and {@code length} are398* assumed to satisfy the preconditions.399*/400@Override401public abstract MappedByteBuffer slice(int index, int length);402403/**404* {@inheritDoc}405*/406@Override407public abstract MappedByteBuffer duplicate();408409/**410* {@inheritDoc}411*/412@Override413public abstract MappedByteBuffer compact();414}415416417