1 /* 2 * Copyright (c) 2000, 2015, 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.util.concurrent.atomic.AtomicLong; 29 30 import jdk.internal.misc.JavaNioAccess; 31 import jdk.internal.misc.JavaLangRefAccess; 32 import jdk.internal.misc.SharedSecrets; 33 import jdk.internal.misc.Unsafe; 34 import jdk.internal.misc.VM; 35 import jdk.internal.ref.CleanerFactory; 36 import jdk.internal.ref.CleanerImpl; 37 38 /** 39 * Access to bits, native and otherwise. 40 */ 41 42 class Bits { // package-private 43 44 private Bits() { } 45 46 47 // -- Swapping -- 48 49 static short swap(short x) { 50 return Short.reverseBytes(x); 51 } 52 53 static char swap(char x) { 54 return Character.reverseBytes(x); 55 } 56 57 static int swap(int x) { 58 return Integer.reverseBytes(x); 59 } 60 61 static long swap(long x) { 62 return Long.reverseBytes(x); 63 } 64 65 66 // -- get/put char -- 67 68 private static char makeChar(byte b1, byte b0) { 69 return (char)((b1 << 8) | (b0 & 0xff)); 70 } 71 72 static char getCharL(ByteBuffer bb, int bi) { 73 return makeChar(bb._get(bi + 1), 74 bb._get(bi )); 75 } 76 77 static char getCharL(long a) { 78 return makeChar(_get(a + 1), 79 _get(a )); 80 } 81 82 static char getCharB(ByteBuffer bb, int bi) { 83 return makeChar(bb._get(bi ), 84 bb._get(bi + 1)); 85 } 86 87 static char getCharB(long a) { 88 return makeChar(_get(a ), 89 _get(a + 1)); 90 } 91 92 static char getChar(ByteBuffer bb, int bi, boolean bigEndian) { 93 return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi); 94 } 95 96 static char getChar(long a, boolean bigEndian) { 97 return bigEndian ? getCharB(a) : getCharL(a); 98 } 99 100 private static byte char1(char x) { return (byte)(x >> 8); } 101 private static byte char0(char x) { return (byte)(x ); } 102 103 static void putCharL(ByteBuffer bb, int bi, char x) { 104 bb._put(bi , char0(x)); 105 bb._put(bi + 1, char1(x)); 106 } 107 108 static void putCharL(long a, char x) { 109 _put(a , char0(x)); 110 _put(a + 1, char1(x)); 111 } 112 113 static void putCharB(ByteBuffer bb, int bi, char x) { 114 bb._put(bi , char1(x)); 115 bb._put(bi + 1, char0(x)); 116 } 117 118 static void putCharB(long a, char x) { 119 _put(a , char1(x)); 120 _put(a + 1, char0(x)); 121 } 122 123 static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) { 124 if (bigEndian) 125 putCharB(bb, bi, x); 126 else 127 putCharL(bb, bi, x); 128 } 129 130 static void putChar(long a, char x, boolean bigEndian) { 131 if (bigEndian) 132 putCharB(a, x); 133 else 134 putCharL(a, x); 135 } 136 137 138 // -- get/put short -- 139 140 private static short makeShort(byte b1, byte b0) { 141 return (short)((b1 << 8) | (b0 & 0xff)); 142 } 143 144 static short getShortL(ByteBuffer bb, int bi) { 145 return makeShort(bb._get(bi + 1), 146 bb._get(bi )); 147 } 148 149 static short getShortL(long a) { 150 return makeShort(_get(a + 1), 151 _get(a )); 152 } 153 154 static short getShortB(ByteBuffer bb, int bi) { 155 return makeShort(bb._get(bi ), 156 bb._get(bi + 1)); 157 } 158 159 static short getShortB(long a) { 160 return makeShort(_get(a ), 161 _get(a + 1)); 162 } 163 164 static short getShort(ByteBuffer bb, int bi, boolean bigEndian) { 165 return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi); 166 } 167 168 static short getShort(long a, boolean bigEndian) { 169 return bigEndian ? getShortB(a) : getShortL(a); 170 } 171 172 private static byte short1(short x) { return (byte)(x >> 8); } 173 private static byte short0(short x) { return (byte)(x ); } 174 175 static void putShortL(ByteBuffer bb, int bi, short x) { 176 bb._put(bi , short0(x)); 177 bb._put(bi + 1, short1(x)); 178 } 179 180 static void putShortL(long a, short x) { 181 _put(a , short0(x)); 182 _put(a + 1, short1(x)); 183 } 184 185 static void putShortB(ByteBuffer bb, int bi, short x) { 186 bb._put(bi , short1(x)); 187 bb._put(bi + 1, short0(x)); 188 } 189 190 static void putShortB(long a, short x) { 191 _put(a , short1(x)); 192 _put(a + 1, short0(x)); 193 } 194 195 static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) { 196 if (bigEndian) 197 putShortB(bb, bi, x); 198 else 199 putShortL(bb, bi, x); 200 } 201 202 static void putShort(long a, short x, boolean bigEndian) { 203 if (bigEndian) 204 putShortB(a, x); 205 else 206 putShortL(a, x); 207 } 208 209 210 // -- get/put int -- 211 212 private static int makeInt(byte b3, byte b2, byte b1, byte b0) { 213 return (((b3 ) << 24) | 214 ((b2 & 0xff) << 16) | 215 ((b1 & 0xff) << 8) | 216 ((b0 & 0xff) )); 217 } 218 219 static int getIntL(ByteBuffer bb, int bi) { 220 return makeInt(bb._get(bi + 3), 221 bb._get(bi + 2), 222 bb._get(bi + 1), 223 bb._get(bi )); 224 } 225 226 static int getIntL(long a) { 227 return makeInt(_get(a + 3), 228 _get(a + 2), 229 _get(a + 1), 230 _get(a )); 231 } 232 233 static int getIntB(ByteBuffer bb, int bi) { 234 return makeInt(bb._get(bi ), 235 bb._get(bi + 1), 236 bb._get(bi + 2), 237 bb._get(bi + 3)); 238 } 239 240 static int getIntB(long a) { 241 return makeInt(_get(a ), 242 _get(a + 1), 243 _get(a + 2), 244 _get(a + 3)); 245 } 246 247 static int getInt(ByteBuffer bb, int bi, boolean bigEndian) { 248 return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ; 249 } 250 251 static int getInt(long a, boolean bigEndian) { 252 return bigEndian ? getIntB(a) : getIntL(a) ; 253 } 254 255 private static byte int3(int x) { return (byte)(x >> 24); } 256 private static byte int2(int x) { return (byte)(x >> 16); } 257 private static byte int1(int x) { return (byte)(x >> 8); } 258 private static byte int0(int x) { return (byte)(x ); } 259 260 static void putIntL(ByteBuffer bb, int bi, int x) { 261 bb._put(bi + 3, int3(x)); 262 bb._put(bi + 2, int2(x)); 263 bb._put(bi + 1, int1(x)); 264 bb._put(bi , int0(x)); 265 } 266 267 static void putIntL(long a, int x) { 268 _put(a + 3, int3(x)); 269 _put(a + 2, int2(x)); 270 _put(a + 1, int1(x)); 271 _put(a , int0(x)); 272 } 273 274 static void putIntB(ByteBuffer bb, int bi, int x) { 275 bb._put(bi , int3(x)); 276 bb._put(bi + 1, int2(x)); 277 bb._put(bi + 2, int1(x)); 278 bb._put(bi + 3, int0(x)); 279 } 280 281 static void putIntB(long a, int x) { 282 _put(a , int3(x)); 283 _put(a + 1, int2(x)); 284 _put(a + 2, int1(x)); 285 _put(a + 3, int0(x)); 286 } 287 288 static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) { 289 if (bigEndian) 290 putIntB(bb, bi, x); 291 else 292 putIntL(bb, bi, x); 293 } 294 295 static void putInt(long a, int x, boolean bigEndian) { 296 if (bigEndian) 297 putIntB(a, x); 298 else 299 putIntL(a, x); 300 } 301 302 303 // -- get/put long -- 304 305 private static long makeLong(byte b7, byte b6, byte b5, byte b4, 306 byte b3, byte b2, byte b1, byte b0) 307 { 308 return ((((long)b7 ) << 56) | 309 (((long)b6 & 0xff) << 48) | 310 (((long)b5 & 0xff) << 40) | 311 (((long)b4 & 0xff) << 32) | 312 (((long)b3 & 0xff) << 24) | 313 (((long)b2 & 0xff) << 16) | 314 (((long)b1 & 0xff) << 8) | 315 (((long)b0 & 0xff) )); 316 } 317 318 static long getLongL(ByteBuffer bb, int bi) { 319 return makeLong(bb._get(bi + 7), 320 bb._get(bi + 6), 321 bb._get(bi + 5), 322 bb._get(bi + 4), 323 bb._get(bi + 3), 324 bb._get(bi + 2), 325 bb._get(bi + 1), 326 bb._get(bi )); 327 } 328 329 static long getLongL(long a) { 330 return makeLong(_get(a + 7), 331 _get(a + 6), 332 _get(a + 5), 333 _get(a + 4), 334 _get(a + 3), 335 _get(a + 2), 336 _get(a + 1), 337 _get(a )); 338 } 339 340 static long getLongB(ByteBuffer bb, int bi) { 341 return makeLong(bb._get(bi ), 342 bb._get(bi + 1), 343 bb._get(bi + 2), 344 bb._get(bi + 3), 345 bb._get(bi + 4), 346 bb._get(bi + 5), 347 bb._get(bi + 6), 348 bb._get(bi + 7)); 349 } 350 351 static long getLongB(long a) { 352 return makeLong(_get(a ), 353 _get(a + 1), 354 _get(a + 2), 355 _get(a + 3), 356 _get(a + 4), 357 _get(a + 5), 358 _get(a + 6), 359 _get(a + 7)); 360 } 361 362 static long getLong(ByteBuffer bb, int bi, boolean bigEndian) { 363 return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi); 364 } 365 366 static long getLong(long a, boolean bigEndian) { 367 return bigEndian ? getLongB(a) : getLongL(a); 368 } 369 370 private static byte long7(long x) { return (byte)(x >> 56); } 371 private static byte long6(long x) { return (byte)(x >> 48); } 372 private static byte long5(long x) { return (byte)(x >> 40); } 373 private static byte long4(long x) { return (byte)(x >> 32); } 374 private static byte long3(long x) { return (byte)(x >> 24); } 375 private static byte long2(long x) { return (byte)(x >> 16); } 376 private static byte long1(long x) { return (byte)(x >> 8); } 377 private static byte long0(long x) { return (byte)(x ); } 378 379 static void putLongL(ByteBuffer bb, int bi, long x) { 380 bb._put(bi + 7, long7(x)); 381 bb._put(bi + 6, long6(x)); 382 bb._put(bi + 5, long5(x)); 383 bb._put(bi + 4, long4(x)); 384 bb._put(bi + 3, long3(x)); 385 bb._put(bi + 2, long2(x)); 386 bb._put(bi + 1, long1(x)); 387 bb._put(bi , long0(x)); 388 } 389 390 static void putLongL(long a, long x) { 391 _put(a + 7, long7(x)); 392 _put(a + 6, long6(x)); 393 _put(a + 5, long5(x)); 394 _put(a + 4, long4(x)); 395 _put(a + 3, long3(x)); 396 _put(a + 2, long2(x)); 397 _put(a + 1, long1(x)); 398 _put(a , long0(x)); 399 } 400 401 static void putLongB(ByteBuffer bb, int bi, long x) { 402 bb._put(bi , long7(x)); 403 bb._put(bi + 1, long6(x)); 404 bb._put(bi + 2, long5(x)); 405 bb._put(bi + 3, long4(x)); 406 bb._put(bi + 4, long3(x)); 407 bb._put(bi + 5, long2(x)); 408 bb._put(bi + 6, long1(x)); 409 bb._put(bi + 7, long0(x)); 410 } 411 412 static void putLongB(long a, long x) { 413 _put(a , long7(x)); 414 _put(a + 1, long6(x)); 415 _put(a + 2, long5(x)); 416 _put(a + 3, long4(x)); 417 _put(a + 4, long3(x)); 418 _put(a + 5, long2(x)); 419 _put(a + 6, long1(x)); 420 _put(a + 7, long0(x)); 421 } 422 423 static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) { 424 if (bigEndian) 425 putLongB(bb, bi, x); 426 else 427 putLongL(bb, bi, x); 428 } 429 430 static void putLong(long a, long x, boolean bigEndian) { 431 if (bigEndian) 432 putLongB(a, x); 433 else 434 putLongL(a, x); 435 } 436 437 438 // -- get/put float -- 439 440 static float getFloatL(ByteBuffer bb, int bi) { 441 return Float.intBitsToFloat(getIntL(bb, bi)); 442 } 443 444 static float getFloatL(long a) { 445 return Float.intBitsToFloat(getIntL(a)); 446 } 447 448 static float getFloatB(ByteBuffer bb, int bi) { 449 return Float.intBitsToFloat(getIntB(bb, bi)); 450 } 451 452 static float getFloatB(long a) { 453 return Float.intBitsToFloat(getIntB(a)); 454 } 455 456 static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) { 457 return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi); 458 } 459 460 static float getFloat(long a, boolean bigEndian) { 461 return bigEndian ? getFloatB(a) : getFloatL(a); 462 } 463 464 static void putFloatL(ByteBuffer bb, int bi, float x) { 465 putIntL(bb, bi, Float.floatToRawIntBits(x)); 466 } 467 468 static void putFloatL(long a, float x) { 469 putIntL(a, Float.floatToRawIntBits(x)); 470 } 471 472 static void putFloatB(ByteBuffer bb, int bi, float x) { 473 putIntB(bb, bi, Float.floatToRawIntBits(x)); 474 } 475 476 static void putFloatB(long a, float x) { 477 putIntB(a, Float.floatToRawIntBits(x)); 478 } 479 480 static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) { 481 if (bigEndian) 482 putFloatB(bb, bi, x); 483 else 484 putFloatL(bb, bi, x); 485 } 486 487 static void putFloat(long a, float x, boolean bigEndian) { 488 if (bigEndian) 489 putFloatB(a, x); 490 else 491 putFloatL(a, x); 492 } 493 494 495 // -- get/put double -- 496 497 static double getDoubleL(ByteBuffer bb, int bi) { 498 return Double.longBitsToDouble(getLongL(bb, bi)); 499 } 500 501 static double getDoubleL(long a) { 502 return Double.longBitsToDouble(getLongL(a)); 503 } 504 505 static double getDoubleB(ByteBuffer bb, int bi) { 506 return Double.longBitsToDouble(getLongB(bb, bi)); 507 } 508 509 static double getDoubleB(long a) { 510 return Double.longBitsToDouble(getLongB(a)); 511 } 512 513 static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) { 514 return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi); 515 } 516 517 static double getDouble(long a, boolean bigEndian) { 518 return bigEndian ? getDoubleB(a) : getDoubleL(a); 519 } 520 521 static void putDoubleL(ByteBuffer bb, int bi, double x) { 522 putLongL(bb, bi, Double.doubleToRawLongBits(x)); 523 } 524 525 static void putDoubleL(long a, double x) { 526 putLongL(a, Double.doubleToRawLongBits(x)); 527 } 528 529 static void putDoubleB(ByteBuffer bb, int bi, double x) { 530 putLongB(bb, bi, Double.doubleToRawLongBits(x)); 531 } 532 533 static void putDoubleB(long a, double x) { 534 putLongB(a, Double.doubleToRawLongBits(x)); 535 } 536 537 static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) { 538 if (bigEndian) 539 putDoubleB(bb, bi, x); 540 else 541 putDoubleL(bb, bi, x); 542 } 543 544 static void putDouble(long a, double x, boolean bigEndian) { 545 if (bigEndian) 546 putDoubleB(a, x); 547 else 548 putDoubleL(a, x); 549 } 550 551 552 // -- Unsafe access -- 553 554 private static final Unsafe unsafe = Unsafe.getUnsafe(); 555 556 private static byte _get(long a) { 557 return unsafe.getByte(a); 558 } 559 560 private static void _put(long a, byte b) { 561 unsafe.putByte(a, b); 562 } 563 564 static Unsafe unsafe() { 565 return unsafe; 566 } 567 568 569 // -- Processor and memory-system properties -- 570 571 private static final ByteOrder byteOrder 572 = unsafe.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; 573 574 static ByteOrder byteOrder() { 575 return byteOrder; 576 } 577 578 private static int pageSize = -1; 579 580 static int pageSize() { 581 if (pageSize == -1) 582 pageSize = unsafe().pageSize(); 583 return pageSize; 584 } 585 586 static int pageCount(long size) { 587 return (int)(size + (long)pageSize() - 1L) / pageSize(); 588 } 589 590 private static boolean unaligned = unsafe.unalignedAccess(); 591 592 static boolean unaligned() { 593 return unaligned; 594 } 595 596 597 // -- Direct memory management -- 598 599 // A user-settable upper limit on the maximum amount of allocatable 600 // direct buffer memory. This value may be changed during VM 601 // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>". 602 private static volatile long maxMemory = VM.maxDirectMemory(); 603 private static final AtomicLong reservedMemory = new AtomicLong(); 604 private static final AtomicLong totalCapacity = new AtomicLong(); 605 private static final AtomicLong count = new AtomicLong(); 606 private static volatile boolean memoryLimitSet; 607 608 // max. number of sleeps during try-reserving with exponentially 609 // increasing delay before throwing OutOfMemoryError: 610 // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) 611 // which means that OOME will be thrown after 0.5 s of trying 612 private static final int MAX_SLEEPS = 9; 613 614 // These methods should be called whenever direct memory is allocated or 615 // freed. They allow the user to control the amount of direct memory 616 // which a process may access. All sizes are specified in bytes. 617 static void reserveMemory(long size, int cap) { 618 619 if (!memoryLimitSet && VM.isBooted()) { 620 maxMemory = VM.maxDirectMemory(); 621 memoryLimitSet = true; 622 } 623 624 // optimist! 625 if (tryReserveMemory(size, cap)) { 626 return; 627 } 628 629 final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); 630 631 // retry while: 632 // - helping enqueue pending Reference objects which includes Cleanable(s) 633 // - helping processing the queue of Cleanable(s) which includes the ones 634 // that free direct buffer memory 635 while (jlra.tryHandlePendingReference() | // use non-short-circuit or 636 CleanerImpl.getCleanerImpl(CleanerFactory.cleaner()).drainQueue()) { 637 if (tryReserveMemory(size, cap)) { 638 return; 639 } 640 } 641 642 // trigger VM's Reference processing 643 System.gc(); 644 645 // a retry loop with exponential back-off delays 646 // (this gives VM some time to do it's job) 647 boolean interrupted = false; 648 try { 649 long sleepTime = 1; 650 int sleeps = 0; 651 while (true) { 652 if (tryReserveMemory(size, cap)) { 653 return; 654 } 655 if (sleeps >= MAX_SLEEPS) { 656 break; 657 } 658 if (!jlra.tryHandlePendingReference() & // use non-short-circuit and 659 !CleanerImpl.getCleanerImpl(CleanerFactory.cleaner()).drainQueue()) { 660 try { 661 Thread.sleep(sleepTime); 662 sleepTime <<= 1; 663 sleeps++; 664 } catch (InterruptedException e) { 665 interrupted = true; 666 } 667 } 668 } 669 670 // no luck 671 throw new OutOfMemoryError("Direct buffer memory"); 672 673 } finally { 674 if (interrupted) { 675 // don't swallow interrupts 676 Thread.currentThread().interrupt(); 677 } 678 } 679 } 680 681 private static boolean tryReserveMemory(long size, int cap) { 682 683 // -XX:MaxDirectMemorySize limits the total capacity rather than the 684 // actual memory usage, which will differ when buffers are page 685 // aligned. 686 long totalCap; 687 while (cap <= maxMemory - (totalCap = totalCapacity.get())) { 688 if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) { 689 reservedMemory.addAndGet(size); 690 count.incrementAndGet(); 691 return true; 692 } 693 } 694 695 return false; 696 } 697 698 699 static void unreserveMemory(long size, int cap) { 700 long cnt = count.decrementAndGet(); 701 long reservedMem = reservedMemory.addAndGet(-size); 702 long totalCap = totalCapacity.addAndGet(-cap); 703 assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; 704 } 705 706 // -- Monitoring of direct buffer usage -- 707 708 static { 709 // setup access to this package in SharedSecrets 710 SharedSecrets.setJavaNioAccess( 711 new JavaNioAccess() { 712 @Override 713 public JavaNioAccess.BufferPool getDirectBufferPool() { 714 return new JavaNioAccess.BufferPool() { 715 @Override 716 public String getName() { 717 return "direct"; 718 } 719 @Override 720 public long getCount() { 721 return Bits.count.get(); 722 } 723 @Override 724 public long getTotalCapacity() { 725 return Bits.totalCapacity.get(); 726 } 727 @Override 728 public long getMemoryUsed() { 729 return Bits.reservedMemory.get(); 730 } 731 }; 732 } 733 @Override 734 public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) { 735 return new DirectByteBuffer(addr, cap, ob); 736 } 737 @Override 738 public void truncate(Buffer buf) { 739 buf.truncate(); 740 } 741 }); 742 } 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 */ 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.copyMemory(src, offset, null, 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 */ 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.copyMemory(null, srcAddr, dst, offset, size); 809 length -= size; 810 srcAddr += size; 811 offset += size; 812 } 813 } 814 815 static void copyFromCharArray(Object src, long srcPos, long dstAddr, 816 long length) 817 { 818 copyFromShortArray(src, srcPos, dstAddr, length); 819 } 820 821 static void copyToCharArray(long srcAddr, Object dst, long dstPos, 822 long length) 823 { 824 copyToShortArray(srcAddr, dst, dstPos, length); 825 } 826 827 static native void copyFromShortArray(Object src, long srcPos, long dstAddr, 828 long length); 829 static native void copyToShortArray(long srcAddr, Object dst, long dstPos, 830 long length); 831 832 static native void copyFromIntArray(Object src, long srcPos, long dstAddr, 833 long length); 834 static native void copyToIntArray(long srcAddr, Object dst, long dstPos, 835 long length); 836 837 static native void copyFromLongArray(Object src, long srcPos, long dstAddr, 838 long length); 839 static native void copyToLongArray(long srcAddr, Object dst, long dstPos, 840 long length); 841 842 }