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