1 /*
   2  * Copyright (c) 2000, 2016, 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 jdk.internal.misc.JavaLangRefAccess;
  29 import jdk.internal.misc.JavaNioAccess;
  30 import jdk.internal.misc.SharedSecrets;
  31 import jdk.internal.misc.Unsafe;
  32 import jdk.internal.misc.VM;
  33 
  34 import java.util.concurrent.atomic.AtomicLong;
  35 
  36 /**
  37  * Access to bits, native and otherwise.
  38  */
  39 
  40 class Bits {                            // package-private
  41 
  42     private Bits() { }
  43 
  44 
  45     // -- Swapping --
  46 
  47     static short swap(short x) {
  48         return Short.reverseBytes(x);
  49     }
  50 
  51     static char swap(char x) {
  52         return Character.reverseBytes(x);
  53     }
  54 
  55     static int swap(int x) {
  56         return Integer.reverseBytes(x);
  57     }
  58 
  59     static long swap(long x) {
  60         return Long.reverseBytes(x);
  61     }
  62 
  63 
  64     // -- Unsafe access --
  65 
  66     private static final Unsafe unsafe = Unsafe.getUnsafe();
  67 
  68     static Unsafe unsafe() {
  69         return unsafe;
  70     }
  71 
  72 
  73     // -- Processor and memory-system properties --
  74 
  75     private static final ByteOrder byteOrder
  76         = unsafe.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
  77 
  78     static ByteOrder byteOrder() {
  79         return byteOrder;
  80     }
  81 
  82     private static int pageSize = -1;
  83 
  84     static int pageSize() {
  85         if (pageSize == -1)
  86             pageSize = unsafe().pageSize();
  87         return pageSize;
  88     }
  89 
  90     static int pageCount(long size) {
  91         return (int)(size + (long)pageSize() - 1L) / pageSize();
  92     }
  93 
  94     private static boolean unaligned = unsafe.unalignedAccess();
  95 
  96     static boolean unaligned() {
  97         return unaligned;
  98     }
  99 
 100 
 101     // -- Direct memory management --
 102 
 103     // A user-settable upper limit on the maximum amount of allocatable
 104     // direct buffer memory.  This value may be changed during VM
 105     // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
 106     private static volatile long maxMemory = VM.maxDirectMemory();
 107     private static final AtomicLong reservedMemory = new AtomicLong();
 108     private static final AtomicLong totalCapacity = new AtomicLong();
 109     private static final AtomicLong count = new AtomicLong();
 110     private static volatile boolean memoryLimitSet;
 111 
 112     // max. number of sleeps during try-reserving with exponentially
 113     // increasing delay before throwing OutOfMemoryError:
 114     // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
 115     // which means that OOME will be thrown after 0.5 s of trying
 116     private static final int MAX_SLEEPS = 9;
 117 
 118     // These methods should be called whenever direct memory is allocated or
 119     // freed.  They allow the user to control the amount of direct memory
 120     // which a process may access.  All sizes are specified in bytes.
 121     static void reserveMemory(long size, int cap) {
 122 
 123         if (!memoryLimitSet && VM.initLevel() >= 1) {
 124             maxMemory = VM.maxDirectMemory();
 125             memoryLimitSet = true;
 126         }
 127 
 128         // optimist!
 129         if (tryReserveMemory(size, cap)) {
 130             return;
 131         }
 132 
 133         final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();
 134         boolean interrupted = false;
 135         try {
 136 
 137             // Retry allocation until success or there are no more
 138             // references (including Cleaners that might free direct
 139             // buffer memory) to process and allocation still fails.
 140             boolean refprocActive;
 141             do {
 142                 try {
 143                     refprocActive = jlra.waitForReferenceProcessing();
 144                 } catch (InterruptedException e) {
 145                     // Defer interrupts and keep trying.
 146                     interrupted = true;
 147                     refprocActive = true;
 148                 }
 149                 if (tryReserveMemory(size, cap)) {
 150                     return;
 151                 }
 152             } while (refprocActive);
 153 
 154             // trigger VM's Reference processing
 155             System.gc();
 156 
 157             // A retry loop with exponential back-off delays.
 158             // Sometimes it would suffice to give up once reference
 159             // processing is complete.  But if there are many threads
 160             // competing for memory, this gives more opportunities for
 161             // any given thread to make progress.  In particular, this
 162             // seems to be enough for a stress test like
 163             // DirectBufferAllocTest to (usually) succeed, while
 164             // without it that test likely fails.  Since failure here
 165             // ends in OOME, there's no need to hurry.
 166             long sleepTime = 1;
 167             int sleeps = 0;
 168             while (true) {
 169                 if (tryReserveMemory(size, cap)) {
 170                     return;
 171                 }
 172                 if (sleeps >= MAX_SLEEPS) {
 173                     break;
 174                 }
 175                 try {
 176                     if (!jlra.waitForReferenceProcessing()) {
 177                         Thread.sleep(sleepTime);
 178                         sleepTime <<= 1;
 179                         sleeps++;
 180                     }
 181                 } catch (InterruptedException e) {
 182                     interrupted = true;
 183                 }
 184             }
 185 
 186             // no luck
 187             throw new OutOfMemoryError("Direct buffer memory");
 188 
 189         } finally {
 190             if (interrupted) {
 191                 // don't swallow interrupts
 192                 Thread.currentThread().interrupt();
 193             }
 194         }
 195     }
 196 
 197     private static boolean tryReserveMemory(long size, int cap) {
 198 
 199         // -XX:MaxDirectMemorySize limits the total capacity rather than the
 200         // actual memory usage, which will differ when buffers are page
 201         // aligned.
 202         long totalCap;
 203         while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
 204             if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
 205                 reservedMemory.addAndGet(size);
 206                 count.incrementAndGet();
 207                 return true;
 208             }
 209         }
 210 
 211         return false;
 212     }
 213 
 214 
 215     static void unreserveMemory(long size, int cap) {
 216         long cnt = count.decrementAndGet();
 217         long reservedMem = reservedMemory.addAndGet(-size);
 218         long totalCap = totalCapacity.addAndGet(-cap);
 219         assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
 220     }
 221 
 222     // -- Monitoring of direct buffer usage --
 223 
 224     static {
 225         // setup access to this package in SharedSecrets
 226         SharedSecrets.setJavaNioAccess(
 227             new JavaNioAccess() {
 228                 @Override
 229                 public JavaNioAccess.BufferPool getDirectBufferPool() {
 230                     return new JavaNioAccess.BufferPool() {
 231                         @Override
 232                         public String getName() {
 233                             return "direct";
 234                         }
 235                         @Override
 236                         public long getCount() {
 237                             return Bits.count.get();
 238                         }
 239                         @Override
 240                         public long getTotalCapacity() {
 241                             return Bits.totalCapacity.get();
 242                         }
 243                         @Override
 244                         public long getMemoryUsed() {
 245                             return Bits.reservedMemory.get();
 246                         }
 247                     };
 248                 }
 249                 @Override
 250                 public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
 251                     return new DirectByteBuffer(addr, cap, ob);
 252                 }
 253                 @Override
 254                 public void truncate(Buffer buf) {
 255                     buf.truncate();
 256                 }
 257         });
 258     }
 259 
 260     // These numbers represent the point at which we have empirically
 261     // determined that the average cost of a JNI call exceeds the expense
 262     // of an element by element copy.  These numbers may change over time.
 263     static final int JNI_COPY_TO_ARRAY_THRESHOLD   = 6;
 264     static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
 265 }