Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/nio/MappedByteBuffer.java
38829 views
/*1* Copyright (c) 2000, 2013, 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 sun.misc.Unsafe;293031/**32* A direct byte buffer whose content is a memory-mapped region of a file.33*34* <p> Mapped byte buffers are created via the {@link35* java.nio.channels.FileChannel#map FileChannel.map} method. This class36* extends the {@link ByteBuffer} class with operations that are specific to37* memory-mapped file regions.38*39* <p> A mapped byte buffer and the file mapping that it represents remain40* valid until the buffer itself is garbage-collected.41*42* <p> The content of a mapped byte buffer can change at any time, for example43* if the content of the corresponding region of the mapped file is changed by44* this program or another. Whether or not such changes occur, and when they45* occur, is operating-system dependent and therefore unspecified.46*47* <a name="inaccess"></a><p> All or part of a mapped byte buffer may become48* inaccessible at any time, for example if the mapped file is truncated. An49* attempt to access an inaccessible region of a mapped byte buffer will not50* change the buffer's content and will cause an unspecified exception to be51* thrown either at the time of the access or at some later time. It is52* therefore strongly recommended that appropriate precautions be taken to53* avoid the manipulation of a mapped file by this program, or by a54* concurrently running program, except to read or write the file's content.55*56* <p> Mapped byte buffers otherwise behave no differently than ordinary direct57* byte buffers. </p>58*59*60* @author Mark Reinhold61* @author JSR-51 Expert Group62* @since 1.463*/6465public abstract class MappedByteBuffer66extends ByteBuffer67{6869// This is a little bit backwards: By rights MappedByteBuffer should be a70// subclass of DirectByteBuffer, but to keep the spec clear and simple, and71// for optimization purposes, it's easier to do it the other way around.72// This works because DirectByteBuffer is a package-private class.7374// For mapped buffers, a FileDescriptor that may be used for mapping75// operations if valid; null if the buffer is not mapped.76private final FileDescriptor fd;7778// This should only be invoked by the DirectByteBuffer constructors79//80MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private81FileDescriptor fd)82{83super(mark, pos, lim, cap);84this.fd = fd;85}8687MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private88super(mark, pos, lim, cap);89this.fd = null;90}9192private void checkMapped() {93if (fd == null)94// Can only happen if a luser explicitly casts a direct byte buffer95throw new UnsupportedOperationException();96}9798// Returns the distance (in bytes) of the buffer from the page aligned address99// of the mapping. Computed each time to avoid storing in every direct buffer.100private long mappingOffset() {101int ps = Bits.pageSize();102long offset = address % ps;103return (offset >= 0) ? offset : (ps + offset);104}105106private long mappingAddress(long mappingOffset) {107return address - mappingOffset;108}109110private long mappingLength(long mappingOffset) {111return (long)capacity() + mappingOffset;112}113114/**115* Tells whether or not this buffer's content is resident in physical116* memory.117*118* <p> A return value of <tt>true</tt> implies that it is highly likely119* that all of the data in this buffer is resident in physical memory and120* may therefore be accessed without incurring any virtual-memory page121* faults or I/O operations. A return value of <tt>false</tt> does not122* necessarily imply that the buffer's content is not resident in physical123* memory.124*125* <p> The returned value is a hint, rather than a guarantee, because the126* underlying operating system may have paged out some of the buffer's data127* by the time that an invocation of this method returns. </p>128*129* @return <tt>true</tt> if it is likely that this buffer's content130* is resident in physical memory131*/132public final boolean isLoaded() {133checkMapped();134if ((address == 0) || (capacity() == 0))135return true;136long offset = mappingOffset();137long length = mappingLength(offset);138return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length));139}140141// not used, but a potential target for a store, see load() for details.142private static byte unused;143144/**145* Loads this buffer's content into physical memory.146*147* <p> This method makes a best effort to ensure that, when it returns,148* this buffer's content is resident in physical memory. Invoking this149* method may cause some number of page faults and I/O operations to150* occur. </p>151*152* @return This buffer153*/154public final MappedByteBuffer load() {155checkMapped();156if ((address == 0) || (capacity() == 0))157return this;158long offset = mappingOffset();159long length = mappingLength(offset);160load0(mappingAddress(offset), length);161162// Read a byte from each page to bring it into memory. A checksum163// is computed as we go along to prevent the compiler from otherwise164// considering the loop as dead code.165Unsafe unsafe = Unsafe.getUnsafe();166int ps = Bits.pageSize();167int count = Bits.pageCount(length);168long a = mappingAddress(offset);169byte x = 0;170for (int i=0; i<count; i++) {171x ^= unsafe.getByte(a);172a += ps;173}174if (unused != 0)175unused = x;176177return this;178}179180/**181* Forces any changes made to this buffer's content to be written to the182* storage device containing the mapped file.183*184* <p> If the file mapped into this buffer resides on a local storage185* device then when this method returns it is guaranteed that all changes186* made to the buffer since it was created, or since this method was last187* invoked, will have been written to that device.188*189* <p> If the file does not reside on a local device then no such guarantee190* is made.191*192* <p> If this buffer was not mapped in read/write mode ({@link193* java.nio.channels.FileChannel.MapMode#READ_WRITE}) then invoking this194* method has no effect. </p>195*196* @return This buffer197*/198public final MappedByteBuffer force() {199checkMapped();200if ((address != 0) && (capacity() != 0)) {201long offset = mappingOffset();202force0(fd, mappingAddress(offset), mappingLength(offset));203}204return this;205}206207private native boolean isLoaded0(long address, long length, int pageCount);208private native void load0(long address, long length);209private native void force0(FileDescriptor fd, long address, long length);210}211212213