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 // BEGIN Android-added: Getter / Setters needed due to unsupported ScopedMemoryAccess. 65 // -- get/put char -- 66 makeChar(byte b1, byte b0)67 static private char makeChar(byte b1, byte b0) { 68 return (char)((b1 << 8) | (b0 & 0xff)); 69 } 70 getCharL(ByteBuffer bb, int bi)71 static char getCharL(ByteBuffer bb, int bi) { 72 return makeChar(bb._get(bi + 1), 73 bb._get(bi )); 74 } 75 getCharL(long a)76 static char getCharL(long a) { 77 return makeChar(_get(a + 1), 78 _get(a )); 79 } 80 getCharB(ByteBuffer bb, int bi)81 static char getCharB(ByteBuffer bb, int bi) { 82 return makeChar(bb._get(bi ), 83 bb._get(bi + 1)); 84 } 85 getCharB(long a)86 static char getCharB(long a) { 87 return makeChar(_get(a ), 88 _get(a + 1)); 89 } 90 getChar(ByteBuffer bb, int bi, boolean bigEndian)91 static char getChar(ByteBuffer bb, int bi, boolean bigEndian) { 92 return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi); 93 } 94 getChar(long a, boolean bigEndian)95 static char getChar(long a, boolean bigEndian) { 96 return bigEndian ? getCharB(a) : getCharL(a); 97 } 98 char1(char x)99 private static byte char1(char x) { return (byte)(x >> 8); } char0(char x)100 private static byte char0(char x) { return (byte)(x ); } 101 putCharL(ByteBuffer bb, int bi, char x)102 static void putCharL(ByteBuffer bb, int bi, char x) { 103 bb._put(bi , char0(x)); 104 bb._put(bi + 1, char1(x)); 105 } 106 putCharL(long a, char x)107 static void putCharL(long a, char x) { 108 _put(a , char0(x)); 109 _put(a + 1, char1(x)); 110 } 111 putCharB(ByteBuffer bb, int bi, char x)112 static void putCharB(ByteBuffer bb, int bi, char x) { 113 bb._put(bi , char1(x)); 114 bb._put(bi + 1, char0(x)); 115 } 116 putCharB(long a, char x)117 static void putCharB(long a, char x) { 118 _put(a , char1(x)); 119 _put(a + 1, char0(x)); 120 } 121 putChar(ByteBuffer bb, int bi, char x, boolean bigEndian)122 static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) { 123 if (bigEndian) 124 putCharB(bb, bi, x); 125 else 126 putCharL(bb, bi, x); 127 } 128 putChar(long a, char x, boolean bigEndian)129 static void putChar(long a, char x, boolean bigEndian) { 130 if (bigEndian) 131 putCharB(a, x); 132 else 133 putCharL(a, x); 134 } 135 136 137 // -- get/put short -- 138 makeShort(byte b1, byte b0)139 static private short makeShort(byte b1, byte b0) { 140 return (short)((b1 << 8) | (b0 & 0xff)); 141 } 142 getShortL(ByteBuffer bb, int bi)143 static short getShortL(ByteBuffer bb, int bi) { 144 return makeShort(bb._get(bi + 1), 145 bb._get(bi )); 146 } 147 getShortL(long a)148 static short getShortL(long a) { 149 return makeShort(_get(a + 1), 150 _get(a )); 151 } 152 getShortB(ByteBuffer bb, int bi)153 static short getShortB(ByteBuffer bb, int bi) { 154 return makeShort(bb._get(bi ), 155 bb._get(bi + 1)); 156 } 157 getShortB(long a)158 static short getShortB(long a) { 159 return makeShort(_get(a ), 160 _get(a + 1)); 161 } 162 getShort(ByteBuffer bb, int bi, boolean bigEndian)163 static short getShort(ByteBuffer bb, int bi, boolean bigEndian) { 164 return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi); 165 } 166 getShort(long a, boolean bigEndian)167 static short getShort(long a, boolean bigEndian) { 168 return bigEndian ? getShortB(a) : getShortL(a); 169 } 170 short1(short x)171 private static byte short1(short x) { return (byte)(x >> 8); } short0(short x)172 private static byte short0(short x) { return (byte)(x ); } 173 putShortL(ByteBuffer bb, int bi, short x)174 static void putShortL(ByteBuffer bb, int bi, short x) { 175 bb._put(bi , short0(x)); 176 bb._put(bi + 1, short1(x)); 177 } 178 putShortL(long a, short x)179 static void putShortL(long a, short x) { 180 _put(a , short0(x)); 181 _put(a + 1, short1(x)); 182 } 183 putShortB(ByteBuffer bb, int bi, short x)184 static void putShortB(ByteBuffer bb, int bi, short x) { 185 bb._put(bi , short1(x)); 186 bb._put(bi + 1, short0(x)); 187 } 188 putShortB(long a, short x)189 static void putShortB(long a, short x) { 190 _put(a , short1(x)); 191 _put(a + 1, short0(x)); 192 } 193 putShort(ByteBuffer bb, int bi, short x, boolean bigEndian)194 static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) { 195 if (bigEndian) 196 putShortB(bb, bi, x); 197 else 198 putShortL(bb, bi, x); 199 } 200 putShort(long a, short x, boolean bigEndian)201 static void putShort(long a, short x, boolean bigEndian) { 202 if (bigEndian) 203 putShortB(a, x); 204 else 205 putShortL(a, x); 206 } 207 208 209 // -- get/put int -- 210 makeInt(byte b3, byte b2, byte b1, byte b0)211 static private int makeInt(byte b3, byte b2, byte b1, byte b0) { 212 return (((b3 ) << 24) | 213 ((b2 & 0xff) << 16) | 214 ((b1 & 0xff) << 8) | 215 ((b0 & 0xff) )); 216 } 217 getIntL(ByteBuffer bb, int bi)218 static int getIntL(ByteBuffer bb, int bi) { 219 return makeInt(bb._get(bi + 3), 220 bb._get(bi + 2), 221 bb._get(bi + 1), 222 bb._get(bi )); 223 } 224 getIntL(long a)225 static int getIntL(long a) { 226 return makeInt(_get(a + 3), 227 _get(a + 2), 228 _get(a + 1), 229 _get(a )); 230 } 231 getIntB(ByteBuffer bb, int bi)232 static int getIntB(ByteBuffer bb, int bi) { 233 return makeInt(bb._get(bi ), 234 bb._get(bi + 1), 235 bb._get(bi + 2), 236 bb._get(bi + 3)); 237 } 238 getIntB(long a)239 static int getIntB(long a) { 240 return makeInt(_get(a ), 241 _get(a + 1), 242 _get(a + 2), 243 _get(a + 3)); 244 } 245 getInt(ByteBuffer bb, int bi, boolean bigEndian)246 static int getInt(ByteBuffer bb, int bi, boolean bigEndian) { 247 return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ; 248 } 249 getInt(long a, boolean bigEndian)250 static int getInt(long a, boolean bigEndian) { 251 return bigEndian ? getIntB(a) : getIntL(a) ; 252 } 253 int3(int x)254 private static byte int3(int x) { return (byte)(x >> 24); } int2(int x)255 private static byte int2(int x) { return (byte)(x >> 16); } int1(int x)256 private static byte int1(int x) { return (byte)(x >> 8); } int0(int x)257 private static byte int0(int x) { return (byte)(x ); } 258 putIntL(ByteBuffer bb, int bi, int x)259 static void putIntL(ByteBuffer bb, int bi, int x) { 260 bb._put(bi + 3, int3(x)); 261 bb._put(bi + 2, int2(x)); 262 bb._put(bi + 1, int1(x)); 263 bb._put(bi , int0(x)); 264 } 265 putIntL(long a, int x)266 static void putIntL(long a, int x) { 267 _put(a + 3, int3(x)); 268 _put(a + 2, int2(x)); 269 _put(a + 1, int1(x)); 270 _put(a , int0(x)); 271 } 272 putIntB(ByteBuffer bb, int bi, int x)273 static void putIntB(ByteBuffer bb, int bi, int x) { 274 bb._put(bi , int3(x)); 275 bb._put(bi + 1, int2(x)); 276 bb._put(bi + 2, int1(x)); 277 bb._put(bi + 3, int0(x)); 278 } 279 putIntB(long a, int x)280 static void putIntB(long a, int x) { 281 _put(a , int3(x)); 282 _put(a + 1, int2(x)); 283 _put(a + 2, int1(x)); 284 _put(a + 3, int0(x)); 285 } 286 putInt(ByteBuffer bb, int bi, int x, boolean bigEndian)287 static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) { 288 if (bigEndian) 289 putIntB(bb, bi, x); 290 else 291 putIntL(bb, bi, x); 292 } 293 putInt(long a, int x, boolean bigEndian)294 static void putInt(long a, int x, boolean bigEndian) { 295 if (bigEndian) 296 putIntB(a, x); 297 else 298 putIntL(a, x); 299 } 300 301 302 // -- get/put long -- 303 makeLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0)304 static private long makeLong(byte b7, byte b6, byte b5, byte b4, 305 byte b3, byte b2, byte b1, byte b0) 306 { 307 return ((((long)b7 ) << 56) | 308 (((long)b6 & 0xff) << 48) | 309 (((long)b5 & 0xff) << 40) | 310 (((long)b4 & 0xff) << 32) | 311 (((long)b3 & 0xff) << 24) | 312 (((long)b2 & 0xff) << 16) | 313 (((long)b1 & 0xff) << 8) | 314 (((long)b0 & 0xff) )); 315 } 316 getLongL(ByteBuffer bb, int bi)317 static long getLongL(ByteBuffer bb, int bi) { 318 return makeLong(bb._get(bi + 7), 319 bb._get(bi + 6), 320 bb._get(bi + 5), 321 bb._get(bi + 4), 322 bb._get(bi + 3), 323 bb._get(bi + 2), 324 bb._get(bi + 1), 325 bb._get(bi )); 326 } 327 getLongL(long a)328 static long getLongL(long a) { 329 return makeLong(_get(a + 7), 330 _get(a + 6), 331 _get(a + 5), 332 _get(a + 4), 333 _get(a + 3), 334 _get(a + 2), 335 _get(a + 1), 336 _get(a )); 337 } 338 getLongB(ByteBuffer bb, int bi)339 static long getLongB(ByteBuffer bb, int bi) { 340 return makeLong(bb._get(bi ), 341 bb._get(bi + 1), 342 bb._get(bi + 2), 343 bb._get(bi + 3), 344 bb._get(bi + 4), 345 bb._get(bi + 5), 346 bb._get(bi + 6), 347 bb._get(bi + 7)); 348 } 349 getLongB(long a)350 static long getLongB(long a) { 351 return makeLong(_get(a ), 352 _get(a + 1), 353 _get(a + 2), 354 _get(a + 3), 355 _get(a + 4), 356 _get(a + 5), 357 _get(a + 6), 358 _get(a + 7)); 359 } 360 getLong(ByteBuffer bb, int bi, boolean bigEndian)361 static long getLong(ByteBuffer bb, int bi, boolean bigEndian) { 362 return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi); 363 } 364 getLong(long a, boolean bigEndian)365 static long getLong(long a, boolean bigEndian) { 366 return bigEndian ? getLongB(a) : getLongL(a); 367 } 368 long7(long x)369 private static byte long7(long x) { return (byte)(x >> 56); } long6(long x)370 private static byte long6(long x) { return (byte)(x >> 48); } long5(long x)371 private static byte long5(long x) { return (byte)(x >> 40); } long4(long x)372 private static byte long4(long x) { return (byte)(x >> 32); } long3(long x)373 private static byte long3(long x) { return (byte)(x >> 24); } long2(long x)374 private static byte long2(long x) { return (byte)(x >> 16); } long1(long x)375 private static byte long1(long x) { return (byte)(x >> 8); } long0(long x)376 private static byte long0(long x) { return (byte)(x ); } 377 putLongL(ByteBuffer bb, int bi, long x)378 static void putLongL(ByteBuffer bb, int bi, long x) { 379 bb._put(bi + 7, long7(x)); 380 bb._put(bi + 6, long6(x)); 381 bb._put(bi + 5, long5(x)); 382 bb._put(bi + 4, long4(x)); 383 bb._put(bi + 3, long3(x)); 384 bb._put(bi + 2, long2(x)); 385 bb._put(bi + 1, long1(x)); 386 bb._put(bi , long0(x)); 387 } 388 putLongL(long a, long x)389 static void putLongL(long a, long x) { 390 _put(a + 7, long7(x)); 391 _put(a + 6, long6(x)); 392 _put(a + 5, long5(x)); 393 _put(a + 4, long4(x)); 394 _put(a + 3, long3(x)); 395 _put(a + 2, long2(x)); 396 _put(a + 1, long1(x)); 397 _put(a , long0(x)); 398 } 399 putLongB(ByteBuffer bb, int bi, long x)400 static void putLongB(ByteBuffer bb, int bi, long x) { 401 bb._put(bi , long7(x)); 402 bb._put(bi + 1, long6(x)); 403 bb._put(bi + 2, long5(x)); 404 bb._put(bi + 3, long4(x)); 405 bb._put(bi + 4, long3(x)); 406 bb._put(bi + 5, long2(x)); 407 bb._put(bi + 6, long1(x)); 408 bb._put(bi + 7, long0(x)); 409 } 410 putLongB(long a, long x)411 static void putLongB(long a, long x) { 412 _put(a , long7(x)); 413 _put(a + 1, long6(x)); 414 _put(a + 2, long5(x)); 415 _put(a + 3, long4(x)); 416 _put(a + 4, long3(x)); 417 _put(a + 5, long2(x)); 418 _put(a + 6, long1(x)); 419 _put(a + 7, long0(x)); 420 } 421 putLong(ByteBuffer bb, int bi, long x, boolean bigEndian)422 static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) { 423 if (bigEndian) 424 putLongB(bb, bi, x); 425 else 426 putLongL(bb, bi, x); 427 } 428 putLong(long a, long x, boolean bigEndian)429 static void putLong(long a, long x, boolean bigEndian) { 430 if (bigEndian) 431 putLongB(a, x); 432 else 433 putLongL(a, x); 434 } 435 436 437 // -- get/put float -- 438 getFloatL(ByteBuffer bb, int bi)439 static float getFloatL(ByteBuffer bb, int bi) { 440 return Float.intBitsToFloat(getIntL(bb, bi)); 441 } 442 getFloatL(long a)443 static float getFloatL(long a) { 444 return Float.intBitsToFloat(getIntL(a)); 445 } 446 getFloatB(ByteBuffer bb, int bi)447 static float getFloatB(ByteBuffer bb, int bi) { 448 return Float.intBitsToFloat(getIntB(bb, bi)); 449 } 450 getFloatB(long a)451 static float getFloatB(long a) { 452 return Float.intBitsToFloat(getIntB(a)); 453 } 454 getFloat(ByteBuffer bb, int bi, boolean bigEndian)455 static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) { 456 return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi); 457 } 458 getFloat(long a, boolean bigEndian)459 static float getFloat(long a, boolean bigEndian) { 460 return bigEndian ? getFloatB(a) : getFloatL(a); 461 } 462 putFloatL(ByteBuffer bb, int bi, float x)463 static void putFloatL(ByteBuffer bb, int bi, float x) { 464 putIntL(bb, bi, Float.floatToRawIntBits(x)); 465 } 466 putFloatL(long a, float x)467 static void putFloatL(long a, float x) { 468 putIntL(a, Float.floatToRawIntBits(x)); 469 } 470 putFloatB(ByteBuffer bb, int bi, float x)471 static void putFloatB(ByteBuffer bb, int bi, float x) { 472 putIntB(bb, bi, Float.floatToRawIntBits(x)); 473 } 474 putFloatB(long a, float x)475 static void putFloatB(long a, float x) { 476 putIntB(a, Float.floatToRawIntBits(x)); 477 } 478 putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian)479 static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) { 480 if (bigEndian) 481 putFloatB(bb, bi, x); 482 else 483 putFloatL(bb, bi, x); 484 } 485 putFloat(long a, float x, boolean bigEndian)486 static void putFloat(long a, float x, boolean bigEndian) { 487 if (bigEndian) 488 putFloatB(a, x); 489 else 490 putFloatL(a, x); 491 } 492 493 494 // -- get/put double -- 495 getDoubleL(ByteBuffer bb, int bi)496 static double getDoubleL(ByteBuffer bb, int bi) { 497 return Double.longBitsToDouble(getLongL(bb, bi)); 498 } 499 getDoubleL(long a)500 static double getDoubleL(long a) { 501 return Double.longBitsToDouble(getLongL(a)); 502 } 503 getDoubleB(ByteBuffer bb, int bi)504 static double getDoubleB(ByteBuffer bb, int bi) { 505 return Double.longBitsToDouble(getLongB(bb, bi)); 506 } 507 getDoubleB(long a)508 static double getDoubleB(long a) { 509 return Double.longBitsToDouble(getLongB(a)); 510 } 511 getDouble(ByteBuffer bb, int bi, boolean bigEndian)512 static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) { 513 return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi); 514 } 515 getDouble(long a, boolean bigEndian)516 static double getDouble(long a, boolean bigEndian) { 517 return bigEndian ? getDoubleB(a) : getDoubleL(a); 518 } 519 putDoubleL(ByteBuffer bb, int bi, double x)520 static void putDoubleL(ByteBuffer bb, int bi, double x) { 521 putLongL(bb, bi, Double.doubleToRawLongBits(x)); 522 } 523 putDoubleL(long a, double x)524 static void putDoubleL(long a, double x) { 525 putLongL(a, Double.doubleToRawLongBits(x)); 526 } 527 putDoubleB(ByteBuffer bb, int bi, double x)528 static void putDoubleB(ByteBuffer bb, int bi, double x) { 529 putLongB(bb, bi, Double.doubleToRawLongBits(x)); 530 } 531 putDoubleB(long a, double x)532 static void putDoubleB(long a, double x) { 533 putLongB(a, Double.doubleToRawLongBits(x)); 534 } 535 putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian)536 static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) { 537 if (bigEndian) 538 putDoubleB(bb, bi, x); 539 else 540 putDoubleL(bb, bi, x); 541 } 542 putDouble(long a, double x, boolean bigEndian)543 static void putDouble(long a, double x, boolean bigEndian) { 544 if (bigEndian) 545 putDoubleB(a, x); 546 else 547 putDoubleL(a, x); 548 } 549 _get(long a)550 private static byte _get(long a) { 551 return UNSAFE.getByte(a); 552 } 553 _put(long a, byte b)554 private static void _put(long a, byte b) { 555 UNSAFE.putByte(a, b); 556 } 557 // END Android-added: Getter / Setters needed due to unsupported ScopedMemoryAccess. 558 559 // -- Unsafe access -- 560 561 private static final Unsafe UNSAFE = Unsafe.getUnsafe(); 562 563 // -- Processor and memory-system properties -- 564 565 private static int PAGE_SIZE = -1; 566 pageSize()567 static int pageSize() { 568 if (PAGE_SIZE == -1) 569 PAGE_SIZE = UNSAFE.pageSize(); 570 return PAGE_SIZE; 571 } 572 pageCount(long size)573 static long pageCount(long size) { 574 return (size + (long)pageSize() - 1L) / pageSize(); 575 } 576 // Android-removed: Remove unused methods. 577 /* 578 private static boolean UNALIGNED = UNSAFE.unalignedAccess(); 579 580 static boolean unaligned() { 581 return UNALIGNED; 582 } 583 */ 584 585 586 // -- Direct memory management -- 587 588 // BEGIN Android-removed: Direct memory management unused on Android. 589 /* 590 // A user-settable upper limit on the maximum amount of allocatable 591 // direct buffer memory. This value may be changed during VM 592 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 593 private static volatile long MAX_MEMORY = VM.maxDirectMemory(); 594 private static final AtomicLong RESERVED_MEMORY = new AtomicLong(); 595 private static final AtomicLong TOTAL_CAPACITY = new AtomicLong(); 596 private static final AtomicLong COUNT = new AtomicLong(); 597 private static volatile boolean MEMORY_LIMIT_SET; 598 599 // max. number of sleeps during try-reserving with exponentially 600 // increasing delay before throwing OutOfMemoryError: 601 // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) 602 // which means that OOME will be thrown after 0.5 s of trying 603 private static final int MAX_SLEEPS = 9; 604 605 // These methods should be called whenever direct memory is allocated or 606 // freed. They allow the user to control the amount of direct memory 607 // which a process may access. All sizes are specified in bytes. 608 static void reserveMemory(long size, long cap) { 609 610 if (!MEMORY_LIMIT_SET && VM.initLevel() >= 1) { 611 MAX_MEMORY = VM.maxDirectMemory(); 612 MEMORY_LIMIT_SET = true; 613 } 614 615 // optimist! 616 if (tryReserveMemory(size, cap)) { 617 return; 618 } 619 620 final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); 621 boolean interrupted = false; 622 try { 623 624 // Retry allocation until success or there are no more 625 // references (including Cleaners that might free direct 626 // buffer memory) to process and allocation still fails. 627 boolean refprocActive; 628 do { 629 try { 630 refprocActive = jlra.waitForReferenceProcessing(); 631 } catch (InterruptedException e) { 632 // Defer interrupts and keep trying. 633 interrupted = true; 634 refprocActive = true; 635 } 636 if (tryReserveMemory(size, cap)) { 637 return; 638 } 639 } while (refprocActive); 640 641 // trigger VM's Reference processing 642 System.gc(); 643 644 // A retry loop with exponential back-off delays. 645 // Sometimes it would suffice to give up once reference 646 // processing is complete. But if there are many threads 647 // competing for memory, this gives more opportunities for 648 // any given thread to make progress. In particular, this 649 // seems to be enough for a stress test like 650 // DirectBufferAllocTest to (usually) succeed, while 651 // without it that test likely fails. Since failure here 652 // ends in OOME, there's no need to hurry. 653 long sleepTime = 1; 654 int sleeps = 0; 655 while (true) { 656 if (tryReserveMemory(size, cap)) { 657 return; 658 } 659 if (sleeps >= MAX_SLEEPS) { 660 break; 661 } 662 try { 663 if (!jlra.waitForReferenceProcessing()) { 664 Thread.sleep(sleepTime); 665 sleepTime <<= 1; 666 sleeps++; 667 } 668 } catch (InterruptedException e) { 669 interrupted = true; 670 } 671 } 672 673 // no luck 674 throw new OutOfMemoryError 675 ("Cannot reserve " 676 + size + " bytes of direct buffer memory (allocated: " 677 + RESERVED_MEMORY.get() + ", limit: " + MAX_MEMORY +")"); 678 679 } finally { 680 if (interrupted) { 681 // don't swallow interrupts 682 Thread.currentThread().interrupt(); 683 } 684 } 685 } 686 687 private static boolean tryReserveMemory(long size, long cap) { 688 689 // -XX:MaxDirectMemorySize limits the total capacity rather than the 690 // actual memory usage, which will differ when buffers are page 691 // aligned. 692 long totalCap; 693 while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) { 694 if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) { 695 RESERVED_MEMORY.addAndGet(size); 696 COUNT.incrementAndGet(); 697 return true; 698 } 699 } 700 701 return false; 702 } 703 704 705 static void unreserveMemory(long size, long cap) { 706 long cnt = COUNT.decrementAndGet(); 707 long reservedMem = RESERVED_MEMORY.addAndGet(-size); 708 long totalCap = TOTAL_CAPACITY.addAndGet(-cap); 709 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; 710 } 711 712 static final BufferPool BUFFER_POOL = new BufferPool() { 713 @Override 714 public String getName() { 715 return "direct"; 716 } 717 @Override 718 public long getCount() { 719 return Bits.COUNT.get(); 720 } 721 @Override 722 public long getTotalCapacity() { 723 return Bits.TOTAL_CAPACITY.get(); 724 } 725 @Override 726 public long getMemoryUsed() { 727 return Bits.RESERVED_MEMORY.get(); 728 } 729 }; 730 731 // These numbers represent the point at which we have empirically 732 // determined that the average cost of a JNI call exceeds the expense 733 // of an element by element copy. These numbers may change over time. 734 static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; 735 static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; 736 */ 737 // END Android-removed: Direct memory management unused on Android. 738 } 739