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 }