rev 12972 : 8140606: Update library code to use internal Unsafe
Reviewed-by: duke

   1 /*
   2  * Copyright (c) 2000, 2013, 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 sun.misc.Unsafe;
  30 
  31 
  32 /**
  33  * A direct byte buffer whose content is a memory-mapped region of a file.
  34  *
  35  * <p> Mapped byte buffers are created via the {@link
  36  * java.nio.channels.FileChannel#map FileChannel.map} method.  This class
  37  * extends the {@link ByteBuffer} class with operations that are specific to
  38  * memory-mapped file regions.
  39  *
  40  * <p> A mapped byte buffer and the file mapping that it represents remain
  41  * valid until the buffer itself is garbage-collected.
  42  *
  43  * <p> The content of a mapped byte buffer can change at any time, for example
  44  * if the content of the corresponding region of the mapped file is changed by
  45  * this program or another.  Whether or not such changes occur, and when they
  46  * occur, is operating-system dependent and therefore unspecified.
  47  *
  48  * <a name="inaccess"></a><p> All or part of a mapped byte buffer may become
  49  * inaccessible at any time, for example if the mapped file is truncated.  An
  50  * attempt to access an inaccessible region of a mapped byte buffer will not
  51  * change the buffer's content and will cause an unspecified exception to be
  52  * thrown either at the time of the access or at some later time.  It is
  53  * therefore strongly recommended that appropriate precautions be taken to
  54  * avoid the manipulation of a mapped file by this program, or by a
  55  * concurrently running program, except to read or write the file's content.
  56  *
  57  * <p> Mapped byte buffers otherwise behave no differently than ordinary direct
  58  * byte buffers. </p>
  59  *
  60  *
  61  * @author Mark Reinhold
  62  * @author JSR-51 Expert Group
  63  * @since 1.4
  64  */
  65 
  66 public abstract class MappedByteBuffer
  67     extends ByteBuffer
  68 {
  69 
  70     // This is a little bit backwards: By rights MappedByteBuffer should be a
  71     // subclass of DirectByteBuffer, but to keep the spec clear and simple, and
  72     // for optimization purposes, it's easier to do it the other way around.
  73     // This works because DirectByteBuffer is a package-private class.
  74 
  75     // For mapped buffers, a FileDescriptor that may be used for mapping
  76     // operations if valid; null if the buffer is not mapped.
  77     private final FileDescriptor fd;
  78 
  79     // This should only be invoked by the DirectByteBuffer constructors
  80     //
  81     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
  82                      FileDescriptor fd)
  83     {
  84         super(mark, pos, lim, cap);
  85         this.fd = fd;
  86     }
  87 
  88     MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
  89         super(mark, pos, lim, cap);
  90         this.fd = null;
  91     }
  92 
  93     private void checkMapped() {
  94         if (fd == null)
  95             // Can only happen if a luser explicitly casts a direct byte buffer
  96             throw new UnsupportedOperationException();
  97     }
  98 
  99     // Returns the distance (in bytes) of the buffer from the page aligned address
 100     // of the mapping. Computed each time to avoid storing in every direct buffer.
 101     private long mappingOffset() {
 102         int ps = Bits.pageSize();
 103         long offset = address % ps;
 104         return (offset >= 0) ? offset : (ps + offset);
 105     }
 106 
 107     private long mappingAddress(long mappingOffset) {
 108         return address - mappingOffset;
 109     }
 110 
 111     private long mappingLength(long mappingOffset) {
 112         return (long)capacity() + mappingOffset;
 113     }
 114 
 115     /**
 116      * Tells whether or not this buffer's content is resident in physical
 117      * memory.
 118      *
 119      * <p> A return value of {@code true} implies that it is highly likely
 120      * that all of the data in this buffer is resident in physical memory and
 121      * may therefore be accessed without incurring any virtual-memory page
 122      * faults or I/O operations.  A return value of {@code false} does not
 123      * necessarily imply that the buffer's content is not resident in physical
 124      * memory.
 125      *
 126      * <p> The returned value is a hint, rather than a guarantee, because the
 127      * underlying operating system may have paged out some of the buffer's data
 128      * by the time that an invocation of this method returns.  </p>
 129      *
 130      * @return  {@code true} if it is likely that this buffer's content
 131      *          is resident in physical memory
 132      */
 133     public final boolean isLoaded() {
 134         checkMapped();
 135         if ((address == 0) || (capacity() == 0))
 136             return true;
 137         long offset = mappingOffset();
 138         long length = mappingLength(offset);
 139         return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length));
 140     }
 141 
 142     // not used, but a potential target for a store, see load() for details.
 143     private static byte unused;
 144 
 145     /**
 146      * Loads this buffer's content into physical memory.
 147      *
 148      * <p> This method makes a best effort to ensure that, when it returns,
 149      * this buffer's content is resident in physical memory.  Invoking this
 150      * method may cause some number of page faults and I/O operations to
 151      * occur. </p>
 152      *
 153      * @return  This buffer
 154      */
 155     public final MappedByteBuffer load() {
 156         checkMapped();
 157         if ((address == 0) || (capacity() == 0))
 158             return this;
 159         long offset = mappingOffset();
 160         long length = mappingLength(offset);
 161         load0(mappingAddress(offset), length);
 162 
 163         // Read a byte from each page to bring it into memory. A checksum
 164         // is computed as we go along to prevent the compiler from otherwise
 165         // considering the loop as dead code.
 166         Unsafe unsafe = Unsafe.getUnsafe();
 167         int ps = Bits.pageSize();
 168         int count = Bits.pageCount(length);
 169         long a = mappingAddress(offset);
 170         byte x = 0;
 171         for (int i=0; i<count; i++) {
 172             x ^= unsafe.getByte(a);
 173             a += ps;
 174         }
 175         if (unused != 0)
 176             unused = x;
 177 
 178         return this;
 179     }
 180 
 181     /**
 182      * Forces any changes made to this buffer's content to be written to the
 183      * storage device containing the mapped file.
 184      *
 185      * <p> If the file mapped into this buffer resides on a local storage
 186      * device then when this method returns it is guaranteed that all changes
 187      * made to the buffer since it was created, or since this method was last
 188      * invoked, will have been written to that device.
 189      *
 190      * <p> If the file does not reside on a local device then no such guarantee
 191      * is made.
 192      *
 193      * <p> If this buffer was not mapped in read/write mode ({@link
 194      * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then invoking this
 195      * method has no effect. </p>
 196      *
 197      * @return  This buffer
 198      */
 199     public final MappedByteBuffer force() {
 200         checkMapped();
 201         if ((address != 0) && (capacity() != 0)) {
 202             long offset = mappingOffset();
 203             force0(fd, mappingAddress(offset), mappingLength(offset));
 204         }
 205         return this;
 206     }
 207 
 208     private native boolean isLoaded0(long address, long length, int pageCount);
 209     private native void load0(long address, long length);
 210     private native void force0(FileDescriptor fd, long address, long length);
 211 
 212     // -- Covariant return type overrides
 213 
 214     /**
 215      * {@inheritDoc}
 216      * @since 1.9
 217      */
 218     @Override
 219     public final MappedByteBuffer position(int newPosition) {
 220         super.position(newPosition);
 221         return this;
 222     }
 223 
 224     /**
 225      * {@inheritDoc}
 226      * @since 1.9
 227      */
 228     @Override
 229     public final MappedByteBuffer limit(int newLimit) {
 230         super.limit(newLimit);
 231         return this;
 232     }
 233 
 234     /**
 235      * {@inheritDoc}
 236      * @since 1.9
 237      */
 238     @Override
 239     public final MappedByteBuffer mark() {
 240         super.mark();
 241         return this;
 242     }
 243 
 244     /**
 245      * {@inheritDoc}
 246      * @since 1.9
 247      */
 248     @Override
 249     public final MappedByteBuffer reset() {
 250         super.reset();
 251         return this;
 252     }
 253 
 254     /**
 255      * {@inheritDoc}
 256      * @since 1.9
 257      */
 258     @Override
 259     public final MappedByteBuffer clear() {
 260         super.clear();
 261         return this;
 262     }
 263 
 264     /**
 265      * {@inheritDoc}
 266      * @since 1.9
 267      */
 268     @Override
 269     public final MappedByteBuffer flip() {
 270         super.flip();
 271         return this;
 272     }
 273 
 274     /**
 275      * {@inheritDoc}
 276      * @since 1.9
 277      */
 278     @Override
 279     public final MappedByteBuffer rewind() {
 280         super.rewind();
 281         return this;
 282     }
 283 }
--- EOF ---