1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2000, 2012, 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.Unsafe; 32 import sun.misc.VM; 33 34 /** 35 * Access to bits, native and otherwise. 36 */ 37 38 class Bits { // package-private 39 Bits()40 private Bits() { 41 } 42 43 44 // -- Swapping -- 45 swap(short x)46 static short swap(short x) { 47 return Short.reverseBytes(x); 48 } 49 swap(char x)50 static char swap(char x) { 51 return Character.reverseBytes(x); 52 } 53 swap(int x)54 static int swap(int x) { 55 return Integer.reverseBytes(x); 56 } 57 swap(long x)58 static long swap(long x) { 59 return Long.reverseBytes(x); 60 } 61 62 63 // -- get/put char -- 64 makeChar(byte b1, byte b0)65 static private char makeChar(byte b1, byte b0) { 66 return (char) ((b1 << 8) | (b0 & 0xff)); 67 } 68 getCharL(ByteBuffer bb, int bi)69 static char getCharL(ByteBuffer bb, int bi) { 70 return makeChar(bb._get(bi + 1), 71 bb._get(bi)); 72 } 73 getCharL(long a)74 static char getCharL(long a) { 75 return makeChar(_get(a + 1), 76 _get(a)); 77 } 78 getCharB(ByteBuffer bb, int bi)79 static char getCharB(ByteBuffer bb, int bi) { 80 return makeChar(bb._get(bi), 81 bb._get(bi + 1)); 82 } 83 getCharB(long a)84 static char getCharB(long a) { 85 return makeChar(_get(a), 86 _get(a + 1)); 87 } 88 getChar(ByteBuffer bb, int bi, boolean bigEndian)89 static char getChar(ByteBuffer bb, int bi, boolean bigEndian) { 90 return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi); 91 } 92 getChar(long a, boolean bigEndian)93 static char getChar(long a, boolean bigEndian) { 94 return bigEndian ? getCharB(a) : getCharL(a); 95 } 96 char1(char x)97 private static byte char1(char x) { 98 return (byte) (x >> 8); 99 } 100 char0(char x)101 private static byte char0(char x) { 102 return (byte) (x); 103 } 104 putCharL(ByteBuffer bb, int bi, char x)105 static void putCharL(ByteBuffer bb, int bi, char x) { 106 bb._put(bi, char0(x)); 107 bb._put(bi + 1, char1(x)); 108 } 109 putCharL(long a, char x)110 static void putCharL(long a, char x) { 111 _put(a, char0(x)); 112 _put(a + 1, char1(x)); 113 } 114 putCharB(ByteBuffer bb, int bi, char x)115 static void putCharB(ByteBuffer bb, int bi, char x) { 116 bb._put(bi, char1(x)); 117 bb._put(bi + 1, char0(x)); 118 } 119 putCharB(long a, char x)120 static void putCharB(long a, char x) { 121 _put(a, char1(x)); 122 _put(a + 1, char0(x)); 123 } 124 putChar(ByteBuffer bb, int bi, char x, boolean bigEndian)125 static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) { 126 if (bigEndian) 127 putCharB(bb, bi, x); 128 else 129 putCharL(bb, bi, x); 130 } 131 putChar(long a, char x, boolean bigEndian)132 static void putChar(long a, char x, boolean bigEndian) { 133 if (bigEndian) 134 putCharB(a, x); 135 else 136 putCharL(a, x); 137 } 138 139 140 // -- get/put short -- 141 makeShort(byte b1, byte b0)142 static private short makeShort(byte b1, byte b0) { 143 return (short) ((b1 << 8) | (b0 & 0xff)); 144 } 145 getShortL(ByteBuffer bb, int bi)146 static short getShortL(ByteBuffer bb, int bi) { 147 return makeShort(bb._get(bi + 1), 148 bb._get(bi)); 149 } 150 getShortL(long a)151 static short getShortL(long a) { 152 return makeShort(_get(a + 1), 153 _get(a)); 154 } 155 getShortB(ByteBuffer bb, int bi)156 static short getShortB(ByteBuffer bb, int bi) { 157 return makeShort(bb._get(bi), 158 bb._get(bi + 1)); 159 } 160 getShortB(long a)161 static short getShortB(long a) { 162 return makeShort(_get(a), 163 _get(a + 1)); 164 } 165 getShort(ByteBuffer bb, int bi, boolean bigEndian)166 static short getShort(ByteBuffer bb, int bi, boolean bigEndian) { 167 return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi); 168 } 169 getShort(long a, boolean bigEndian)170 static short getShort(long a, boolean bigEndian) { 171 return bigEndian ? getShortB(a) : getShortL(a); 172 } 173 short1(short x)174 private static byte short1(short x) { 175 return (byte) (x >> 8); 176 } 177 short0(short x)178 private static byte short0(short x) { 179 return (byte) (x); 180 } 181 putShortL(ByteBuffer bb, int bi, short x)182 static void putShortL(ByteBuffer bb, int bi, short x) { 183 bb._put(bi, short0(x)); 184 bb._put(bi + 1, short1(x)); 185 } 186 putShortL(long a, short x)187 static void putShortL(long a, short x) { 188 _put(a, short0(x)); 189 _put(a + 1, short1(x)); 190 } 191 putShortB(ByteBuffer bb, int bi, short x)192 static void putShortB(ByteBuffer bb, int bi, short x) { 193 bb._put(bi, short1(x)); 194 bb._put(bi + 1, short0(x)); 195 } 196 putShortB(long a, short x)197 static void putShortB(long a, short x) { 198 _put(a, short1(x)); 199 _put(a + 1, short0(x)); 200 } 201 putShort(ByteBuffer bb, int bi, short x, boolean bigEndian)202 static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) { 203 if (bigEndian) 204 putShortB(bb, bi, x); 205 else 206 putShortL(bb, bi, x); 207 } 208 putShort(long a, short x, boolean bigEndian)209 static void putShort(long a, short x, boolean bigEndian) { 210 if (bigEndian) 211 putShortB(a, x); 212 else 213 putShortL(a, x); 214 } 215 216 217 // -- get/put int -- 218 makeInt(byte b3, byte b2, byte b1, byte b0)219 static private int makeInt(byte b3, byte b2, byte b1, byte b0) { 220 return (((b3) << 24) | 221 ((b2 & 0xff) << 16) | 222 ((b1 & 0xff) << 8) | 223 ((b0 & 0xff))); 224 } 225 getIntL(ByteBuffer bb, int bi)226 static int getIntL(ByteBuffer bb, int bi) { 227 return makeInt(bb._get(bi + 3), 228 bb._get(bi + 2), 229 bb._get(bi + 1), 230 bb._get(bi)); 231 } 232 getIntL(long a)233 static int getIntL(long a) { 234 return makeInt(_get(a + 3), 235 _get(a + 2), 236 _get(a + 1), 237 _get(a)); 238 } 239 getIntB(ByteBuffer bb, int bi)240 static int getIntB(ByteBuffer bb, int bi) { 241 return makeInt(bb._get(bi), 242 bb._get(bi + 1), 243 bb._get(bi + 2), 244 bb._get(bi + 3)); 245 } 246 getIntB(long a)247 static int getIntB(long a) { 248 return makeInt(_get(a), 249 _get(a + 1), 250 _get(a + 2), 251 _get(a + 3)); 252 } 253 getInt(ByteBuffer bb, int bi, boolean bigEndian)254 static int getInt(ByteBuffer bb, int bi, boolean bigEndian) { 255 return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi); 256 } 257 getInt(long a, boolean bigEndian)258 static int getInt(long a, boolean bigEndian) { 259 return bigEndian ? getIntB(a) : getIntL(a); 260 } 261 int3(int x)262 private static byte int3(int x) { 263 return (byte) (x >> 24); 264 } 265 int2(int x)266 private static byte int2(int x) { 267 return (byte) (x >> 16); 268 } 269 int1(int x)270 private static byte int1(int x) { 271 return (byte) (x >> 8); 272 } 273 int0(int x)274 private static byte int0(int x) { 275 return (byte) (x); 276 } 277 putIntL(ByteBuffer bb, int bi, int x)278 static void putIntL(ByteBuffer bb, int bi, int x) { 279 bb._put(bi + 3, int3(x)); 280 bb._put(bi + 2, int2(x)); 281 bb._put(bi + 1, int1(x)); 282 bb._put(bi, int0(x)); 283 } 284 putIntL(long a, int x)285 static void putIntL(long a, int x) { 286 _put(a + 3, int3(x)); 287 _put(a + 2, int2(x)); 288 _put(a + 1, int1(x)); 289 _put(a, int0(x)); 290 } 291 putIntB(ByteBuffer bb, int bi, int x)292 static void putIntB(ByteBuffer bb, int bi, int x) { 293 bb._put(bi, int3(x)); 294 bb._put(bi + 1, int2(x)); 295 bb._put(bi + 2, int1(x)); 296 bb._put(bi + 3, int0(x)); 297 } 298 putIntB(long a, int x)299 static void putIntB(long a, int x) { 300 _put(a, int3(x)); 301 _put(a + 1, int2(x)); 302 _put(a + 2, int1(x)); 303 _put(a + 3, int0(x)); 304 } 305 putInt(ByteBuffer bb, int bi, int x, boolean bigEndian)306 static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) { 307 if (bigEndian) 308 putIntB(bb, bi, x); 309 else 310 putIntL(bb, bi, x); 311 } 312 putInt(long a, int x, boolean bigEndian)313 static void putInt(long a, int x, boolean bigEndian) { 314 if (bigEndian) 315 putIntB(a, x); 316 else 317 putIntL(a, x); 318 } 319 320 321 // -- get/put long -- 322 makeLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0)323 static private long makeLong(byte b7, byte b6, byte b5, byte b4, 324 byte b3, byte b2, byte b1, byte b0) { 325 return ((((long) b7) << 56) | 326 (((long) b6 & 0xff) << 48) | 327 (((long) b5 & 0xff) << 40) | 328 (((long) b4 & 0xff) << 32) | 329 (((long) b3 & 0xff) << 24) | 330 (((long) b2 & 0xff) << 16) | 331 (((long) b1 & 0xff) << 8) | 332 (((long) b0 & 0xff))); 333 } 334 getLongL(ByteBuffer bb, int bi)335 static long getLongL(ByteBuffer bb, int bi) { 336 return makeLong(bb._get(bi + 7), 337 bb._get(bi + 6), 338 bb._get(bi + 5), 339 bb._get(bi + 4), 340 bb._get(bi + 3), 341 bb._get(bi + 2), 342 bb._get(bi + 1), 343 bb._get(bi)); 344 } 345 getLongL(long a)346 static long getLongL(long a) { 347 return makeLong(_get(a + 7), 348 _get(a + 6), 349 _get(a + 5), 350 _get(a + 4), 351 _get(a + 3), 352 _get(a + 2), 353 _get(a + 1), 354 _get(a)); 355 } 356 getLongB(ByteBuffer bb, int bi)357 static long getLongB(ByteBuffer bb, int bi) { 358 return makeLong(bb._get(bi), 359 bb._get(bi + 1), 360 bb._get(bi + 2), 361 bb._get(bi + 3), 362 bb._get(bi + 4), 363 bb._get(bi + 5), 364 bb._get(bi + 6), 365 bb._get(bi + 7)); 366 } 367 getLongB(long a)368 static long getLongB(long a) { 369 return makeLong(_get(a), 370 _get(a + 1), 371 _get(a + 2), 372 _get(a + 3), 373 _get(a + 4), 374 _get(a + 5), 375 _get(a + 6), 376 _get(a + 7)); 377 } 378 getLong(ByteBuffer bb, int bi, boolean bigEndian)379 static long getLong(ByteBuffer bb, int bi, boolean bigEndian) { 380 return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi); 381 } 382 getLong(long a, boolean bigEndian)383 static long getLong(long a, boolean bigEndian) { 384 return bigEndian ? getLongB(a) : getLongL(a); 385 } 386 long7(long x)387 private static byte long7(long x) { 388 return (byte) (x >> 56); 389 } 390 long6(long x)391 private static byte long6(long x) { 392 return (byte) (x >> 48); 393 } 394 long5(long x)395 private static byte long5(long x) { 396 return (byte) (x >> 40); 397 } 398 long4(long x)399 private static byte long4(long x) { 400 return (byte) (x >> 32); 401 } 402 long3(long x)403 private static byte long3(long x) { 404 return (byte) (x >> 24); 405 } 406 long2(long x)407 private static byte long2(long x) { 408 return (byte) (x >> 16); 409 } 410 long1(long x)411 private static byte long1(long x) { 412 return (byte) (x >> 8); 413 } 414 long0(long x)415 private static byte long0(long x) { 416 return (byte) (x); 417 } 418 putLongL(ByteBuffer bb, int bi, long x)419 static void putLongL(ByteBuffer bb, int bi, long x) { 420 bb._put(bi + 7, long7(x)); 421 bb._put(bi + 6, long6(x)); 422 bb._put(bi + 5, long5(x)); 423 bb._put(bi + 4, long4(x)); 424 bb._put(bi + 3, long3(x)); 425 bb._put(bi + 2, long2(x)); 426 bb._put(bi + 1, long1(x)); 427 bb._put(bi, long0(x)); 428 } 429 putLongL(long a, long x)430 static void putLongL(long a, long x) { 431 _put(a + 7, long7(x)); 432 _put(a + 6, long6(x)); 433 _put(a + 5, long5(x)); 434 _put(a + 4, long4(x)); 435 _put(a + 3, long3(x)); 436 _put(a + 2, long2(x)); 437 _put(a + 1, long1(x)); 438 _put(a, long0(x)); 439 } 440 putLongB(ByteBuffer bb, int bi, long x)441 static void putLongB(ByteBuffer bb, int bi, long x) { 442 bb._put(bi, long7(x)); 443 bb._put(bi + 1, long6(x)); 444 bb._put(bi + 2, long5(x)); 445 bb._put(bi + 3, long4(x)); 446 bb._put(bi + 4, long3(x)); 447 bb._put(bi + 5, long2(x)); 448 bb._put(bi + 6, long1(x)); 449 bb._put(bi + 7, long0(x)); 450 } 451 putLongB(long a, long x)452 static void putLongB(long a, long x) { 453 _put(a, long7(x)); 454 _put(a + 1, long6(x)); 455 _put(a + 2, long5(x)); 456 _put(a + 3, long4(x)); 457 _put(a + 4, long3(x)); 458 _put(a + 5, long2(x)); 459 _put(a + 6, long1(x)); 460 _put(a + 7, long0(x)); 461 } 462 putLong(ByteBuffer bb, int bi, long x, boolean bigEndian)463 static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) { 464 if (bigEndian) 465 putLongB(bb, bi, x); 466 else 467 putLongL(bb, bi, x); 468 } 469 putLong(long a, long x, boolean bigEndian)470 static void putLong(long a, long x, boolean bigEndian) { 471 if (bigEndian) 472 putLongB(a, x); 473 else 474 putLongL(a, x); 475 } 476 477 478 // -- get/put float -- 479 getFloatL(ByteBuffer bb, int bi)480 static float getFloatL(ByteBuffer bb, int bi) { 481 return Float.intBitsToFloat(getIntL(bb, bi)); 482 } 483 getFloatL(long a)484 static float getFloatL(long a) { 485 return Float.intBitsToFloat(getIntL(a)); 486 } 487 getFloatB(ByteBuffer bb, int bi)488 static float getFloatB(ByteBuffer bb, int bi) { 489 return Float.intBitsToFloat(getIntB(bb, bi)); 490 } 491 getFloatB(long a)492 static float getFloatB(long a) { 493 return Float.intBitsToFloat(getIntB(a)); 494 } 495 getFloat(ByteBuffer bb, int bi, boolean bigEndian)496 static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) { 497 return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi); 498 } 499 getFloat(long a, boolean bigEndian)500 static float getFloat(long a, boolean bigEndian) { 501 return bigEndian ? getFloatB(a) : getFloatL(a); 502 } 503 putFloatL(ByteBuffer bb, int bi, float x)504 static void putFloatL(ByteBuffer bb, int bi, float x) { 505 putIntL(bb, bi, Float.floatToRawIntBits(x)); 506 } 507 putFloatL(long a, float x)508 static void putFloatL(long a, float x) { 509 putIntL(a, Float.floatToRawIntBits(x)); 510 } 511 putFloatB(ByteBuffer bb, int bi, float x)512 static void putFloatB(ByteBuffer bb, int bi, float x) { 513 putIntB(bb, bi, Float.floatToRawIntBits(x)); 514 } 515 putFloatB(long a, float x)516 static void putFloatB(long a, float x) { 517 putIntB(a, Float.floatToRawIntBits(x)); 518 } 519 putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian)520 static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) { 521 if (bigEndian) 522 putFloatB(bb, bi, x); 523 else 524 putFloatL(bb, bi, x); 525 } 526 putFloat(long a, float x, boolean bigEndian)527 static void putFloat(long a, float x, boolean bigEndian) { 528 if (bigEndian) 529 putFloatB(a, x); 530 else 531 putFloatL(a, x); 532 } 533 534 535 // -- get/put double -- 536 getDoubleL(ByteBuffer bb, int bi)537 static double getDoubleL(ByteBuffer bb, int bi) { 538 return Double.longBitsToDouble(getLongL(bb, bi)); 539 } 540 getDoubleL(long a)541 static double getDoubleL(long a) { 542 return Double.longBitsToDouble(getLongL(a)); 543 } 544 getDoubleB(ByteBuffer bb, int bi)545 static double getDoubleB(ByteBuffer bb, int bi) { 546 return Double.longBitsToDouble(getLongB(bb, bi)); 547 } 548 getDoubleB(long a)549 static double getDoubleB(long a) { 550 return Double.longBitsToDouble(getLongB(a)); 551 } 552 getDouble(ByteBuffer bb, int bi, boolean bigEndian)553 static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) { 554 return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi); 555 } 556 getDouble(long a, boolean bigEndian)557 static double getDouble(long a, boolean bigEndian) { 558 return bigEndian ? getDoubleB(a) : getDoubleL(a); 559 } 560 putDoubleL(ByteBuffer bb, int bi, double x)561 static void putDoubleL(ByteBuffer bb, int bi, double x) { 562 putLongL(bb, bi, Double.doubleToRawLongBits(x)); 563 } 564 putDoubleL(long a, double x)565 static void putDoubleL(long a, double x) { 566 putLongL(a, Double.doubleToRawLongBits(x)); 567 } 568 putDoubleB(ByteBuffer bb, int bi, double x)569 static void putDoubleB(ByteBuffer bb, int bi, double x) { 570 putLongB(bb, bi, Double.doubleToRawLongBits(x)); 571 } 572 putDoubleB(long a, double x)573 static void putDoubleB(long a, double x) { 574 putLongB(a, Double.doubleToRawLongBits(x)); 575 } 576 putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian)577 static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) { 578 if (bigEndian) 579 putDoubleB(bb, bi, x); 580 else 581 putDoubleL(bb, bi, x); 582 } 583 putDouble(long a, double x, boolean bigEndian)584 static void putDouble(long a, double x, boolean bigEndian) { 585 if (bigEndian) 586 putDoubleB(a, x); 587 else 588 putDoubleL(a, x); 589 } 590 591 592 // -- Unsafe access -- 593 594 private static final Unsafe unsafe = Unsafe.getUnsafe(); 595 _get(long a)596 private static byte _get(long a) { 597 return unsafe.getByte(a); 598 } 599 _put(long a, byte b)600 private static void _put(long a, byte b) { 601 unsafe.putByte(a, b); 602 } 603 unsafe()604 static Unsafe unsafe() { 605 return unsafe; 606 } 607 608 609 // -- Processor and memory-system properties -- 610 611 /* ----- BEGIN android ----- 612 private static final ByteOrder byteOrder;*/ 613 private static final ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN; 614 // ----- END android ----- 615 byteOrder()616 static ByteOrder byteOrder() { 617 // Android changed : android is always little endian. 618 return byteOrder; 619 620 /* ----- BEGIN android ----- 621 if (byteOrder == null) 622 throw new Error("Unknown byte order"); 623 if (byteOrder == null) { 624 long a = unsafe.allocateMemory(8); 625 try { 626 unsafe.putLong(a, 0x0102030405060708L); 627 byte b = unsafe.getByte(a); 628 switch (b) { 629 case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break; 630 case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break; 631 default: throw new Error("Unknown byte order"); 632 } 633 } finally { 634 unsafe.freeMemory(a); 635 } 636 } 637 return byteOrder; 638 */ 639 } 640 641 /* ----- BEGIN android ----- 642 static { 643 long a = unsafe.allocateMemory(8); 644 try { 645 unsafe.putLong(a, 0x0102030405060708L); 646 byte b = unsafe.getByte(a); 647 switch (b) { 648 case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break; 649 case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break; 650 default: 651 assert false; 652 byteOrder = null; 653 } 654 } finally { 655 unsafe.freeMemory(a); 656 } 657 } 658 ----- END android ----- */ 659 660 661 private static int pageSize = -1; 662 pageSize()663 static int pageSize() { 664 if (pageSize == -1) 665 pageSize = unsafe().pageSize(); 666 return pageSize; 667 } 668 pageCount(long size)669 static int pageCount(long size) { 670 return (int) (size + (long) pageSize() - 1L) / pageSize(); 671 } 672 673 private static boolean unaligned; 674 private static boolean unalignedKnown = false; 675 unaligned()676 static boolean unaligned() { 677 if (unalignedKnown) 678 return unaligned; 679 String arch = AccessController.doPrivileged( 680 new sun.security.action.GetPropertyAction("os.arch")); 681 unaligned = arch.equals("i386") || arch.equals("x86") 682 || arch.equals("amd64") || arch.equals("x86_64"); 683 unalignedKnown = true; 684 return unaligned; 685 } 686 687 688 // -- Direct memory management -- 689 690 // A user-settable upper limit on the maximum amount of allocatable 691 // direct buffer memory. This value may be changed during VM 692 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 693 private static volatile long maxMemory = VM.maxDirectMemory(); 694 private static volatile long reservedMemory; 695 private static volatile long totalCapacity; 696 private static volatile long count; 697 private static boolean memoryLimitSet = false; 698 699 // These methods should be called whenever direct memory is allocated or 700 // freed. They allow the user to control the amount of direct memory 701 // which a process may access. All sizes are specified in bytes. reserveMemory(long size, int cap)702 static void reserveMemory(long size, int cap) { 703 synchronized (Bits.class) { 704 if (!memoryLimitSet && VM.isBooted()) { 705 maxMemory = VM.maxDirectMemory(); 706 memoryLimitSet = true; 707 } 708 // -XX:MaxDirectMemorySize limits the total capacity rather than the 709 // actual memory usage, which will differ when buffers are page 710 // aligned. 711 if (cap <= maxMemory - totalCapacity) { 712 reservedMemory += size; 713 totalCapacity += cap; 714 count++; 715 return; 716 } 717 } 718 719 System.gc(); 720 try { 721 Thread.sleep(100); 722 } catch (InterruptedException x) { 723 // Restore interrupt status 724 Thread.currentThread().interrupt(); 725 } 726 synchronized (Bits.class) { 727 if (totalCapacity + cap > maxMemory) 728 throw new OutOfMemoryError("Direct buffer memory"); 729 reservedMemory += size; 730 totalCapacity += cap; 731 count++; 732 } 733 734 } 735 unreserveMemory(long size, int cap)736 static synchronized void unreserveMemory(long size, int cap) { 737 if (reservedMemory > 0) { 738 reservedMemory -= size; 739 totalCapacity -= cap; 740 count--; 741 assert (reservedMemory > -1); 742 } 743 } 744 745 // -- Monitoring of direct buffer usage -- 746 747 /* ----- BEGIN android ----- 748 static { 749 // setup access to this package in SharedSecrets 750 sun.misc.SharedSecrets.setJavaNioAccess( 751 new sun.misc.JavaNioAccess() { 752 @Override 753 public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() { 754 return new sun.misc.JavaNioAccess.BufferPool() { 755 @Override 756 public String getName() { 757 return "direct"; 758 } 759 @Override 760 public long getCount() { 761 return Bits.count; 762 } 763 @Override 764 public long getTotalCapacity() { 765 return Bits.totalCapacity; 766 } 767 @Override 768 public long getMemoryUsed() { 769 return Bits.reservedMemory; 770 } 771 }; 772 } 773 @Override 774 public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) { 775 return new DirectByteBuffer(addr, cap, ob); 776 } 777 @Override 778 public void truncate(Buffer buf) { 779 buf.truncate(); 780 } 781 }); 782 } 783 ----- END android ----- */ 784 785 // -- Bulk get/put acceleration -- 786 787 // These numbers represent the point at which we have empirically 788 // determined that the average cost of a JNI call exceeds the expense 789 // of an element by element copy. These numbers may change over time. 790 static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; 791 static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; 792 793 // This number limits the number of bytes to copy per call to Unsafe's 794 // copyMemory method. A limit is imposed to allow for safepoint polling 795 // during a large copy 796 static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L; 797 798 // These methods do no bounds checking. Verification that the copy will not 799 // result in memory corruption should be done prior to invocation. 800 // All positions and lengths are specified in bytes. 801 802 /** 803 * Copy from given source array to destination address. 804 * 805 * @param src source array 806 * @param srcBaseOffset offset of first element of storage in source array 807 * @param srcPos offset within source array of the first element to read 808 * @param dstAddr destination address 809 * @param length number of bytes to copy 810 */ copyFromArray(Object src, long srcBaseOffset, long srcPos, long dstAddr, long length)811 static void copyFromArray(Object src, long srcBaseOffset, long srcPos, 812 long dstAddr, long length) { 813 long offset = srcBaseOffset + srcPos; 814 while (length > 0) { 815 long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; 816 unsafe.copyMemoryFromPrimitiveArray(src, offset, dstAddr, size); 817 length -= size; 818 offset += size; 819 dstAddr += size; 820 } 821 } 822 823 /** 824 * Copy from source address into given destination array. 825 * 826 * @param srcAddr source address 827 * @param dst destination array 828 * @param dstBaseOffset offset of first element of storage in destination array 829 * @param dstPos offset within destination array of the first element to write 830 * @param length number of bytes to copy 831 */ copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos, long length)832 static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos, 833 long length) { 834 long offset = dstBaseOffset + dstPos; 835 while (length > 0) { 836 long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; 837 unsafe.copyMemoryToPrimitiveArray(srcAddr, dst, offset, size); 838 length -= size; 839 srcAddr += size; 840 offset += size; 841 } 842 } 843 copyFromCharArray(Object src, long srcPos, long dstAddr, long length)844 static void copyFromCharArray(Object src, long srcPos, long dstAddr, 845 long length) { 846 copyFromShortArray(src, srcPos, dstAddr, length); 847 } 848 copyToCharArray(long srcAddr, Object dst, long dstPos, long length)849 static void copyToCharArray(long srcAddr, Object dst, long dstPos, 850 long length) { 851 copyToShortArray(srcAddr, dst, dstPos, length); 852 } 853 copyFromShortArray(Object src, long srcPos, long dstAddr, long length)854 static native void copyFromShortArray(Object src, long srcPos, long dstAddr, 855 long length); 856 copyToShortArray(long srcAddr, Object dst, long dstPos, long length)857 static native void copyToShortArray(long srcAddr, Object dst, long dstPos, 858 long length); 859 copyFromIntArray(Object src, long srcPos, long dstAddr, long length)860 static native void copyFromIntArray(Object src, long srcPos, long dstAddr, 861 long length); 862 copyToIntArray(long srcAddr, Object dst, long dstPos, long length)863 static native void copyToIntArray(long srcAddr, Object dst, long dstPos, 864 long length); 865 copyFromLongArray(Object src, long srcPos, long dstAddr, long length)866 static native void copyFromLongArray(Object src, long srcPos, long dstAddr, 867 long length); 868 copyToLongArray(long srcAddr, Object dst, long dstPos, long length)869 static native void copyToLongArray(long srcAddr, Object dst, long dstPos, 870 long length); 871 872 } 873