1 /* 2 * Copyright (c) 2000, 2012, 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 java.security.AccessController; 29 import java.util.concurrent.atomic.AtomicLong; 30 import java.util.concurrent.atomic.LongAdder; 31 32 import sun.misc.JavaLangRefAccess; 33 import sun.misc.SharedSecrets; 34 import sun.misc.Unsafe; 35 import sun.misc.VM; 36 37 /** 38 * Access to bits, native and otherwise. 39 */ 40 41 class Bits { // package-private 42 43 private Bits() { } 44 45 46 // -- Swapping -- 47 48 static short swap(short x) { 49 return Short.reverseBytes(x); 50 } 51 52 static char swap(char x) { 53 return Character.reverseBytes(x); 54 } 55 56 static int swap(int x) { 57 return Integer.reverseBytes(x); 58 } 59 60 static long swap(long x) { 61 return Long.reverseBytes(x); 62 } 63 64 65 // -- get/put char -- 66 67 static private char makeChar(byte b1, byte b0) { 68 return (char)((b1 << 8) | (b0 & 0xff)); 69 } 70 71 static char getCharL(ByteBuffer bb, int bi) { 72 return makeChar(bb._get(bi + 1), 73 bb._get(bi )); 74 } 75 76 static char getCharL(long a) { 77 return makeChar(_get(a + 1), 78 _get(a )); 79 } 80 81 static char getCharB(ByteBuffer bb, int bi) { 82 return makeChar(bb._get(bi ), 83 bb._get(bi + 1)); 84 } 85 86 static char getCharB(long a) { 87 return makeChar(_get(a ), 88 _get(a + 1)); 89 } 90 91 static char getChar(ByteBuffer bb, int bi, boolean bigEndian) { 92 return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi); 93 } 94 95 static char getChar(long a, boolean bigEndian) { 96 return bigEndian ? getCharB(a) : getCharL(a); 97 } 98 99 private static byte char1(char x) { return (byte)(x >> 8); } 100 private static byte char0(char x) { return (byte)(x ); } 101 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 107 static void putCharL(long a, char x) { 108 _put(a , char0(x)); 109 _put(a + 1, char1(x)); 110 } 111 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 117 static void putCharB(long a, char x) { 118 _put(a , char1(x)); 119 _put(a + 1, char0(x)); 120 } 121 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 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 139 static private short makeShort(byte b1, byte b0) { 140 return (short)((b1 << 8) | (b0 & 0xff)); 141 } 142 143 static short getShortL(ByteBuffer bb, int bi) { 144 return makeShort(bb._get(bi + 1), 145 bb._get(bi )); 146 } 147 148 static short getShortL(long a) { 149 return makeShort(_get(a + 1), 150 _get(a )); 151 } 152 153 static short getShortB(ByteBuffer bb, int bi) { 154 return makeShort(bb._get(bi ), 155 bb._get(bi + 1)); 156 } 157 158 static short getShortB(long a) { 159 return makeShort(_get(a ), 160 _get(a + 1)); 161 } 162 163 static short getShort(ByteBuffer bb, int bi, boolean bigEndian) { 164 return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi); 165 } 166 167 static short getShort(long a, boolean bigEndian) { 168 return bigEndian ? getShortB(a) : getShortL(a); 169 } 170 171 private static byte short1(short x) { return (byte)(x >> 8); } 172 private static byte short0(short x) { return (byte)(x ); } 173 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 179 static void putShortL(long a, short x) { 180 _put(a , short0(x)); 181 _put(a + 1, short1(x)); 182 } 183 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 189 static void putShortB(long a, short x) { 190 _put(a , short1(x)); 191 _put(a + 1, short0(x)); 192 } 193 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 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 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 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 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 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 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 246 static int getInt(ByteBuffer bb, int bi, boolean bigEndian) { 247 return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ; 248 } 249 250 static int getInt(long a, boolean bigEndian) { 251 return bigEndian ? getIntB(a) : getIntL(a) ; 252 } 253 254 private static byte int3(int x) { return (byte)(x >> 24); } 255 private static byte int2(int x) { return (byte)(x >> 16); } 256 private static byte int1(int x) { return (byte)(x >> 8); } 257 private static byte int0(int x) { return (byte)(x ); } 258 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 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 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 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 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 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 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 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 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 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 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 361 static long getLong(ByteBuffer bb, int bi, boolean bigEndian) { 362 return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi); 363 } 364 365 static long getLong(long a, boolean bigEndian) { 366 return bigEndian ? getLongB(a) : getLongL(a); 367 } 368 369 private static byte long7(long x) { return (byte)(x >> 56); } 370 private static byte long6(long x) { return (byte)(x >> 48); } 371 private static byte long5(long x) { return (byte)(x >> 40); } 372 private static byte long4(long x) { return (byte)(x >> 32); } 373 private static byte long3(long x) { return (byte)(x >> 24); } 374 private static byte long2(long x) { return (byte)(x >> 16); } 375 private static byte long1(long x) { return (byte)(x >> 8); } 376 private static byte long0(long x) { return (byte)(x ); } 377 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 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 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 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 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 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 439 static float getFloatL(ByteBuffer bb, int bi) { 440 return Float.intBitsToFloat(getIntL(bb, bi)); 441 } 442 443 static float getFloatL(long a) { 444 return Float.intBitsToFloat(getIntL(a)); 445 } 446 447 static float getFloatB(ByteBuffer bb, int bi) { 448 return Float.intBitsToFloat(getIntB(bb, bi)); 449 } 450 451 static float getFloatB(long a) { 452 return Float.intBitsToFloat(getIntB(a)); 453 } 454 455 static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) { 456 return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi); 457 } 458 459 static float getFloat(long a, boolean bigEndian) { 460 return bigEndian ? getFloatB(a) : getFloatL(a); 461 } 462 463 static void putFloatL(ByteBuffer bb, int bi, float x) { 464 putIntL(bb, bi, Float.floatToRawIntBits(x)); 465 } 466 467 static void putFloatL(long a, float x) { 468 putIntL(a, Float.floatToRawIntBits(x)); 469 } 470 471 static void putFloatB(ByteBuffer bb, int bi, float x) { 472 putIntB(bb, bi, Float.floatToRawIntBits(x)); 473 } 474 475 static void putFloatB(long a, float x) { 476 putIntB(a, Float.floatToRawIntBits(x)); 477 } 478 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 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 496 static double getDoubleL(ByteBuffer bb, int bi) { 497 return Double.longBitsToDouble(getLongL(bb, bi)); 498 } 499 500 static double getDoubleL(long a) { 501 return Double.longBitsToDouble(getLongL(a)); 502 } 503 504 static double getDoubleB(ByteBuffer bb, int bi) { 505 return Double.longBitsToDouble(getLongB(bb, bi)); 506 } 507 508 static double getDoubleB(long a) { 509 return Double.longBitsToDouble(getLongB(a)); 510 } 511 512 static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) { 513 return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi); 514 } 515 516 static double getDouble(long a, boolean bigEndian) { 517 return bigEndian ? getDoubleB(a) : getDoubleL(a); 518 } 519 520 static void putDoubleL(ByteBuffer bb, int bi, double x) { 521 putLongL(bb, bi, Double.doubleToRawLongBits(x)); 522 } 523 524 static void putDoubleL(long a, double x) { 525 putLongL(a, Double.doubleToRawLongBits(x)); 526 } 527 528 static void putDoubleB(ByteBuffer bb, int bi, double x) { 529 putLongB(bb, bi, Double.doubleToRawLongBits(x)); 530 } 531 532 static void putDoubleB(long a, double x) { 533 putLongB(a, Double.doubleToRawLongBits(x)); 534 } 535 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 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 550 551 // -- Unsafe access -- 552 553 private static final Unsafe unsafe = Unsafe.getUnsafe(); 554 555 private static byte _get(long a) { 556 return unsafe.getByte(a); 557 } 558 559 private static void _put(long a, byte b) { 560 unsafe.putByte(a, b); 561 } 562 563 static Unsafe unsafe() { 564 return unsafe; 565 } 566 567 568 // -- Processor and memory-system properties -- 569 570 private static final ByteOrder byteOrder; 571 572 static ByteOrder byteOrder() { 573 if (byteOrder == null) 574 throw new Error("Unknown byte order"); 575 return byteOrder; 576 } 577 578 static { 579 long a = unsafe.allocateMemory(8); 580 try { 581 unsafe.putLong(a, 0x0102030405060708L); 582 byte b = unsafe.getByte(a); 583 switch (b) { 584 case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break; 585 case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break; 586 default: 587 assert false; 588 byteOrder = null; 589 } 590 } finally { 591 unsafe.freeMemory(a); 592 } 593 } 594 595 596 private static int pageSize = -1; 597 598 static int pageSize() { 599 if (pageSize == -1) 600 pageSize = unsafe().pageSize(); 601 return pageSize; 602 } 603 604 static int pageCount(long size) { 605 return (int)(size + (long)pageSize() - 1L) / pageSize(); 606 } 607 608 private static boolean unaligned; 609 private static boolean unalignedKnown = false; 610 611 static boolean unaligned() { 612 if (unalignedKnown) 613 return unaligned; 614 String arch = AccessController.doPrivileged( 615 new sun.security.action.GetPropertyAction("os.arch")); 616 unaligned = arch.equals("i386") || arch.equals("x86") 617 || arch.equals("amd64") || arch.equals("x86_64"); 618 unalignedKnown = true; 619 return unaligned; 620 } 621 622 623 // -- Direct memory management -- 624 625 // A user-settable upper limit on the maximum amount of allocatable 626 // direct buffer memory. This value may be changed during VM 627 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 628 private static volatile long maxMemory = VM.maxDirectMemory(); 629 private static final AtomicLong reservedMemory = new AtomicLong(); 630 private static final AtomicLong totalCapacity = new AtomicLong(); 631 private static final AtomicLong count = new AtomicLong(); 632 private static volatile boolean memoryLimitSet = false; 633 // max. number of sleeps during try-reserving with exponentially 634 // increasing delay before throwing OutOfMemoryError: 635 // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) 636 // which means that OOME will be thrown after 0.5 s of trying 637 private static final int MAX_SLEEPS = 9; 638 639 // These methods should be called whenever direct memory is allocated or 640 // freed. They allow the user to control the amount of direct memory 641 // which a process may access. All sizes are specified in bytes. 642 static void reserveMemory(long size, int cap) { 643 644 if (!memoryLimitSet && VM.isBooted()) { 645 maxMemory = VM.maxDirectMemory(); 646 memoryLimitSet = true; 647 } 648 649 // optimist! 650 if (tryReserveMemory(size, cap)) { 651 return; 652 } 653 654 final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); 655 656 // retry while helping enqueue pending Reference objects 657 // which includes executing pending Cleaner(s) which includes 658 // Cleaner(s) that free direct buffer memory 659 while (jlra.tryHandlePendingReference()) { 660 if (tryReserveMemory(size, cap)) { 661 return; 662 } 663 } 664 665 // trigger VM's Reference processing 666 System.gc(); 667 668 // a retry loop with exponential back-off delays 669 // (this gives VM some time to do it's job) 670 boolean interrupted = false; 671 try { 672 long sleepTime = 1; 673 int sleeps = 0; 674 while (true) { 675 if (tryReserveMemory(size, cap)) { 676 return; 677 } 678 if (sleeps >= MAX_SLEEPS) { 679 break; 680 } 681 if (!jlra.tryHandlePendingReference()) { 682 try { 683 Thread.sleep(sleepTime); 684 sleepTime <<= 1; 685 sleeps++; 686 } catch (InterruptedException e) { 687 interrupted = true; 688 } 689 } 690 } 691 692 // no luck 693 throw new OutOfMemoryError("Direct buffer memory"); 694 695 } finally { 696 if (interrupted) { 697 // don't swallow interrupts 698 Thread.currentThread().interrupt(); 699 } 700 } 701 } 702 703 private static boolean tryReserveMemory(long size, int cap) { 704 705 // -XX:MaxDirectMemorySize limits the total capacity rather than the 706 // actual memory usage, which will differ when buffers are page 707 // aligned. 708 long totalCap; 709 while (cap <= maxMemory - (totalCap = totalCapacity.get())) { 710 if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) { 711 reservedMemory.addAndGet(size); 712 count.incrementAndGet(); 713 return true; 714 } 715 } 716 717 return false; 718 } 719 720 721 static void unreserveMemory(long size, int cap) { 722 long cnt = count.decrementAndGet(); 723 long reservedMem = reservedMemory.addAndGet(-size); 724 long totalCap = totalCapacity.addAndGet(-cap); 725 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; 726 } 727 728 // -- Monitoring of direct buffer usage -- 729 730 static { 731 // setup access to this package in SharedSecrets 732 sun.misc.SharedSecrets.setJavaNioAccess( 733 new sun.misc.JavaNioAccess() { 734 @Override 735 public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() { 736 return new sun.misc.JavaNioAccess.BufferPool() { 737 @Override 738 public String getName() { 739 return "direct"; 740 } 741 @Override 742 public long getCount() { 743 return Bits.count.get(); 744 } 745 @Override 746 public long getTotalCapacity() { 747 return Bits.totalCapacity.get(); 748 } 749 @Override 750 public long getMemoryUsed() { 751 return Bits.reservedMemory.get(); 752 } 753 }; 754 } 755 @Override 756 public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) { 757 return new DirectByteBuffer(addr, cap, ob); 758 } 759 @Override 760 public void truncate(Buffer buf) { 761 buf.truncate(); 762 } 763 }); 764 } 765 766 // -- Bulk get/put acceleration -- 767 768 // These numbers represent the point at which we have empirically 769 // determined that the average cost of a JNI call exceeds the expense 770 // of an element by element copy. These numbers may change over time. 771 static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; 772 static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; 773 774 // This number limits the number of bytes to copy per call to Unsafe's 775 // copyMemory method. A limit is imposed to allow for safepoint polling 776 // during a large copy 777 static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L; 778 779 // These methods do no bounds checking. Verification that the copy will not 780 // result in memory corruption should be done prior to invocation. 781 // All positions and lengths are specified in bytes. 782 783 /** 784 * Copy from given source array to destination address. 785 * 786 * @param src 787 * source array 788 * @param srcBaseOffset 789 * offset of first element of storage in source array 790 * @param srcPos 791 * offset within source array of the first element to read 792 * @param dstAddr 793 * destination address 794 * @param length 795 * number of bytes to copy 796 */ 797 static void copyFromArray(Object src, long srcBaseOffset, long srcPos, 798 long dstAddr, long length) 799 { 800 long offset = srcBaseOffset + srcPos; 801 while (length > 0) { 802 long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; 803 unsafe.copyMemory(src, offset, null, dstAddr, size); 804 length -= size; 805 offset += size; 806 dstAddr += size; 807 } 808 } 809 810 /** 811 * Copy from source address into given destination array. 812 * 813 * @param srcAddr 814 * source address 815 * @param dst 816 * destination array 817 * @param dstBaseOffset 818 * offset of first element of storage in destination array 819 * @param dstPos 820 * offset within destination array of the first element to write 821 * @param length 822 * number of bytes to copy 823 */ 824 static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos, 825 long length) 826 { 827 long offset = dstBaseOffset + dstPos; 828 while (length > 0) { 829 long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; 830 unsafe.copyMemory(null, srcAddr, dst, offset, size); 831 length -= size; 832 srcAddr += size; 833 offset += size; 834 } 835 } 836 837 static void copyFromCharArray(Object src, long srcPos, long dstAddr, 838 long length) 839 { 840 copyFromShortArray(src, srcPos, dstAddr, length); 841 } 842 843 static void copyToCharArray(long srcAddr, Object dst, long dstPos, 844 long length) 845 { 846 copyToShortArray(srcAddr, dst, dstPos, length); 847 } 848 849 static native void copyFromShortArray(Object src, long srcPos, long dstAddr, 850 long length); 851 static native void copyToShortArray(long srcAddr, Object dst, long dstPos, 852 long length); 853 854 static native void copyFromIntArray(Object src, long srcPos, long dstAddr, 855 long length); 856 static native void copyToIntArray(long srcAddr, Object dst, long dstPos, 857 long length); 858 859 static native void copyFromLongArray(Object src, long srcPos, long dstAddr, 860 long length); 861 static native void copyToLongArray(long srcAddr, Object dst, long dstPos, 862 long length); 863 864 }