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 }