1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.nio; 28 29 import java.security.AccessController; 30 31 import sun.misc.VM; 32 import jdk.internal.access.SharedSecrets; 33 import jdk.internal.misc.Unsafe; 34 35 import java.util.concurrent.atomic.AtomicLong; 36 37 /** 38 * Access to bits, native and otherwise. 39 */ 40 41 class Bits { // package-private 42 Bits()43 private Bits() { } 44 45 46 // -- Swapping -- 47 swap(short x)48 static short swap(short x) { 49 return Short.reverseBytes(x); 50 } 51 swap(char x)52 static char swap(char x) { 53 return Character.reverseBytes(x); 54 } 55 swap(int x)56 static int swap(int x) { 57 return Integer.reverseBytes(x); 58 } 59 swap(long x)60 static long swap(long x) { 61 return Long.reverseBytes(x); 62 } 63 64 65 // -- Unsafe access -- 66 67 private static final Unsafe UNSAFE = Unsafe.getUnsafe(); 68 69 // -- Processor and memory-system properties -- 70 71 private static int PAGE_SIZE = -1; 72 pageSize()73 static int pageSize() { 74 if (PAGE_SIZE == -1) 75 PAGE_SIZE = UNSAFE.pageSize(); 76 return PAGE_SIZE; 77 } 78 pageCount(long size)79 static long pageCount(long size) { 80 return (size + (long)pageSize() - 1L) / pageSize(); 81 } 82 // Android-removed: Remove unused methods. 83 /* 84 private static boolean UNALIGNED = UNSAFE.unalignedAccess(); 85 86 static boolean unaligned() { 87 return UNALIGNED; 88 } 89 */ 90 91 92 // -- Direct memory management -- 93 94 // BEGIN Android-removed: Direct memory management unused on Android. 95 /* 96 // A user-settable upper limit on the maximum amount of allocatable 97 // direct buffer memory. This value may be changed during VM 98 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 99 private static volatile long MAX_MEMORY = VM.maxDirectMemory(); 100 private static final AtomicLong RESERVED_MEMORY = new AtomicLong(); 101 private static final AtomicLong TOTAL_CAPACITY = new AtomicLong(); 102 private static final AtomicLong COUNT = new AtomicLong(); 103 private static volatile boolean MEMORY_LIMIT_SET; 104 105 // max. number of sleeps during try-reserving with exponentially 106 // increasing delay before throwing OutOfMemoryError: 107 // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) 108 // which means that OOME will be thrown after 0.5 s of trying 109 private static final int MAX_SLEEPS = 9; 110 111 // These methods should be called whenever direct memory is allocated or 112 // freed. They allow the user to control the amount of direct memory 113 // which a process may access. All sizes are specified in bytes. 114 static void reserveMemory(long size, long cap) { 115 116 if (!MEMORY_LIMIT_SET && VM.initLevel() >= 1) { 117 MAX_MEMORY = VM.maxDirectMemory(); 118 MEMORY_LIMIT_SET = true; 119 } 120 121 // optimist! 122 if (tryReserveMemory(size, cap)) { 123 return; 124 } 125 126 final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); 127 boolean interrupted = false; 128 try { 129 130 // Retry allocation until success or there are no more 131 // references (including Cleaners that might free direct 132 // buffer memory) to process and allocation still fails. 133 boolean refprocActive; 134 do { 135 try { 136 refprocActive = jlra.waitForReferenceProcessing(); 137 } catch (InterruptedException e) { 138 // Defer interrupts and keep trying. 139 interrupted = true; 140 refprocActive = true; 141 } 142 if (tryReserveMemory(size, cap)) { 143 return; 144 } 145 } while (refprocActive); 146 147 // trigger VM's Reference processing 148 System.gc(); 149 150 // A retry loop with exponential back-off delays. 151 // Sometimes it would suffice to give up once reference 152 // processing is complete. But if there are many threads 153 // competing for memory, this gives more opportunities for 154 // any given thread to make progress. In particular, this 155 // seems to be enough for a stress test like 156 // DirectBufferAllocTest to (usually) succeed, while 157 // without it that test likely fails. Since failure here 158 // ends in OOME, there's no need to hurry. 159 long sleepTime = 1; 160 int sleeps = 0; 161 while (true) { 162 if (tryReserveMemory(size, cap)) { 163 return; 164 } 165 if (sleeps >= MAX_SLEEPS) { 166 break; 167 } 168 try { 169 if (!jlra.waitForReferenceProcessing()) { 170 Thread.sleep(sleepTime); 171 sleepTime <<= 1; 172 sleeps++; 173 } 174 } catch (InterruptedException e) { 175 interrupted = true; 176 } 177 } 178 179 // no luck 180 throw new OutOfMemoryError 181 ("Cannot reserve " 182 + size + " bytes of direct buffer memory (allocated: " 183 + RESERVED_MEMORY.get() + ", limit: " + MAX_MEMORY +")"); 184 185 } finally { 186 if (interrupted) { 187 // don't swallow interrupts 188 Thread.currentThread().interrupt(); 189 } 190 } 191 } 192 193 private static boolean tryReserveMemory(long size, long cap) { 194 195 // -XX:MaxDirectMemorySize limits the total capacity rather than the 196 // actual memory usage, which will differ when buffers are page 197 // aligned. 198 long totalCap; 199 while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) { 200 if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) { 201 RESERVED_MEMORY.addAndGet(size); 202 COUNT.incrementAndGet(); 203 return true; 204 } 205 } 206 207 return false; 208 } 209 210 211 static void unreserveMemory(long size, long cap) { 212 long cnt = COUNT.decrementAndGet(); 213 long reservedMem = RESERVED_MEMORY.addAndGet(-size); 214 long totalCap = TOTAL_CAPACITY.addAndGet(-cap); 215 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; 216 } 217 218 static final BufferPool BUFFER_POOL = new BufferPool() { 219 @Override 220 public String getName() { 221 return "direct"; 222 } 223 @Override 224 public long getCount() { 225 return Bits.COUNT.get(); 226 } 227 @Override 228 public long getTotalCapacity() { 229 return Bits.TOTAL_CAPACITY.get(); 230 } 231 @Override 232 public long getMemoryUsed() { 233 return Bits.RESERVED_MEMORY.get(); 234 } 235 }; 236 237 // These numbers represent the point at which we have empirically 238 // determined that the average cost of a JNI call exceeds the expense 239 // of an element by element copy. These numbers may change over time. 240 static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; 241 static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; 242 */ 243 // END Android-removed: Direct memory management unused on Android. 244 } 245