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