1 /*
   2  * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any 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)((x << 8) |
  45                        ((char)x >>> 8));
  46     }
  47 
  48     static char swap(char x) {
  49         return (char)((x << 8) |
  50                       (x >>> 8));
  51     }
  52 
  53     static int swap(int x) {
  54         return ((x << 24) |
  55                 ((x & 0x0000ff00) <<  8) |
  56                 ((x & 0x00ff0000) >>> 8) |
  57                 (x >>> 24));
  58     }
  59 
  60     static long swap(long x) {
  61         return (((long)swap((int)x) << 32) |
  62                 ((long)swap((int)(x >>> 32)) & 0xffffffffL));
  63     }
  64 
  65 
  66     // -- get/put char --
  67 
  68     static private 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 + 0));
  75     }
  76 
  77     static char getCharL(long a) {
  78         return makeChar(_get(a + 1),
  79                         _get(a + 0));
  80     }
  81 
  82     static char getCharB(ByteBuffer bb, int bi) {
  83         return makeChar(bb._get(bi + 0),
  84                         bb._get(bi + 1));
  85     }
  86 
  87     static char getCharB(long a) {
  88         return makeChar(_get(a + 0),
  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 >> 0); }
 102 
 103     static void putCharL(ByteBuffer bb, int bi, char x) {
 104         bb._put(bi + 0, char0(x));
 105         bb._put(bi + 1, char1(x));
 106     }
 107 
 108     static void putCharL(long a, char x) {
 109         _put(a + 0, char0(x));
 110         _put(a + 1, char1(x));
 111     }
 112 
 113     static void putCharB(ByteBuffer bb, int bi, char x) {
 114         bb._put(bi + 0, char1(x));
 115         bb._put(bi + 1, char0(x));
 116     }
 117 
 118     static void putCharB(long a, char x) {
 119         _put(a + 0, 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     static private 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 + 0));
 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 + 0),
 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 >> 0); }
 174 
 175     static void putShortL(ByteBuffer bb, int bi, short x) {
 176         bb._put(bi + 0, 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 + 0, 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     static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
 213         return (((b3 & 0xff) << 24) |
 214                 ((b2 & 0xff) << 16) |
 215                 ((b1 & 0xff) <<  8) |
 216                 ((b0 & 0xff) <<  0));
 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 + 0));
 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 + 0));
 231     }
 232 
 233     static int getIntB(ByteBuffer bb, int bi) {
 234         return makeInt(bb._get(bi + 0),
 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 + 0),
 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 >>  0); }
 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 + 0, 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 + 0, int0(x));
 272     }
 273 
 274     static void putIntB(ByteBuffer bb, int bi, int x) {
 275         bb._put(bi + 0, 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 + 0, 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     static private long makeLong(byte b7, byte b6, byte b5, byte b4,
 306                                  byte b3, byte b2, byte b1, byte b0)
 307     {
 308         return ((((long)b7 & 0xff) << 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) <<  0));
 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 + 0));
 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 + 0));
 338     }
 339 
 340     static long getLongB(ByteBuffer bb, int bi) {
 341         return makeLong(bb._get(bi + 0),
 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 + 0),
 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 >>  0); }
 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 + 0, 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 + 0, long0(x));
 399     }
 400 
 401     static void putLongB(ByteBuffer bb, int bi, long x) {
 402         bb._put(bi + 0, 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 + 0, 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 
 573     static ByteOrder byteOrder() {
 574         if (byteOrder == null)
 575             throw new Error("Unknown byte order");
 576         return byteOrder;
 577     }
 578 
 579     static {
 580         long a = unsafe.allocateMemory(8);
 581         try {
 582             unsafe.putLong(a, 0x0102030405060708L);
 583             byte b = unsafe.getByte(a);
 584             switch (b) {
 585             case 0x01: byteOrder = ByteOrder.BIG_ENDIAN;     break;
 586             case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN;  break;
 587             default:
 588                 assert false;
 589                 byteOrder = null;
 590             }
 591         } finally {
 592             unsafe.freeMemory(a);
 593         }
 594     }
 595 
 596 
 597     private static int pageSize = -1;
 598 
 599     static int pageSize() {
 600         if (pageSize == -1)
 601             pageSize = unsafe().pageSize();
 602         return pageSize;
 603     }
 604 
 605 
 606     private static boolean unaligned;
 607     private static boolean unalignedKnown = false;
 608 
 609     static boolean unaligned() {
 610         if (unalignedKnown)
 611             return unaligned;
 612         String arch = AccessController.doPrivileged(
 613             new sun.security.action.GetPropertyAction("os.arch"));
 614         unaligned = arch.equals("i386") || arch.equals("x86")
 615             || arch.equals("amd64");
 616         unalignedKnown = true;
 617         return unaligned;
 618     }
 619 
 620 
 621     // -- Direct memory management --
 622 
 623     // A user-settable upper limit on the maximum amount of allocatable
 624     // direct buffer memory.  This value may be changed during VM
 625     // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
 626     private static volatile long maxMemory = VM.maxDirectMemory();
 627     private static volatile long reservedMemory;
 628     private static volatile long usedMemory;
 629     private static volatile long count;
 630     private static boolean memoryLimitSet = false;
 631 
 632     // These methods should be called whenever direct memory is allocated or
 633     // freed.  They allow the user to control the amount of direct memory
 634     // which a process may access.  All sizes are specified in bytes.
 635     static void reserveMemory(long size, int cap) {
 636 
 637         synchronized (Bits.class) {
 638             if (!memoryLimitSet && VM.isBooted()) {
 639                 maxMemory = VM.maxDirectMemory();
 640                 memoryLimitSet = true;
 641             }
 642             if (size <= maxMemory - reservedMemory) {
 643                 reservedMemory += size;
 644                 usedMemory += cap;
 645                 count++;
 646                 return;
 647             }
 648         }
 649 
 650         System.gc();
 651         try {
 652             Thread.sleep(100);
 653         } catch (InterruptedException x) {
 654             // Restore interrupt status
 655             Thread.currentThread().interrupt();
 656         }
 657         synchronized (Bits.class) {
 658             if (reservedMemory + size > maxMemory)
 659                 throw new OutOfMemoryError("Direct buffer memory");
 660             reservedMemory += size;
 661             usedMemory += cap;
 662             count++;
 663         }
 664 
 665     }
 666 
 667     static synchronized void unreserveMemory(long size, int cap) {
 668         if (reservedMemory > 0) {
 669             reservedMemory -= size;
 670             usedMemory -= cap;
 671             count--;
 672             assert (reservedMemory > -1);
 673         }
 674     }
 675 
 676     // -- Monitoring of direct buffer usage --
 677 
 678     static {
 679         // setup access to this package in SharedSecrets
 680         sun.misc.SharedSecrets.setJavaNioAccess(
 681             new sun.misc.JavaNioAccess() {
 682                 @Override
 683                 public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() {
 684                     return new sun.misc.JavaNioAccess.BufferPool() {
 685                         @Override
 686                         public String getName() {
 687                             return "direct";
 688                         }
 689                         @Override
 690                         public long getCount() {
 691                             return Bits.count;
 692                         }
 693                         @Override
 694                         public long getTotalCapacity() {
 695                             return Bits.usedMemory;
 696                         }
 697                         @Override
 698                         public long getMemoryUsed() {
 699                             return Bits.reservedMemory;
 700                         }
 701                     };
 702                 }
 703         });
 704     }
 705 
 706     // -- Bulk get/put acceleration --
 707 
 708     // These numbers represent the point at which we have empirically
 709     // determined that the average cost of a JNI call exceeds the expense
 710     // of an element by element copy.  These numbers may change over time.
 711     static final int JNI_COPY_TO_ARRAY_THRESHOLD   = 6;
 712     static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
 713 
 714     // This number limits the number of bytes to copy per call to Unsafe's
 715     // copyMemory method. A limit is imposed to allow for safepoint polling
 716     // during a large copy
 717     static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
 718 
 719     // These methods do no bounds checking.  Verification that the copy will not
 720     // result in memory corruption should be done prior to invocation.
 721     // All positions and lengths are specified in bytes.
 722 
 723     /**
 724      * Copy from given source array to destination address.
 725      *
 726      * @param   src
 727      *          source array
 728      * @param   srcBaseOffset
 729      *          offset of first element of storage in source array
 730      * @param   srcPos
 731      *          offset within source array of the first element to read
 732      * @param   dstAddr
 733      *          destination address
 734      * @param   length
 735      *          number of bytes to copy
 736      */
 737     static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
 738                               long dstAddr, long length)
 739     {
 740         long offset = srcBaseOffset + srcPos;
 741         while (length > 0) {
 742             long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
 743             unsafe.copyMemory(src, offset, null, dstAddr, size);
 744             length -= size;
 745             offset += size;
 746             dstAddr += size;
 747         }
 748     }
 749 
 750     /**
 751      * Copy from source address into given destination array.
 752      *
 753      * @param   srcAddr
 754      *          source address
 755      * @param   dst
 756      *          destination array
 757      * @param   dstBaseOffset
 758      *          offset of first element of storage in destination array
 759      * @param   dstPos
 760      *          offset within destination array of the first element to write
 761      * @param   length
 762      *          number of bytes to copy
 763      */
 764     static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,
 765                             long length)
 766     {
 767         long offset = dstBaseOffset + dstPos;
 768         while (length > 0) {
 769             long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
 770             unsafe.copyMemory(null, srcAddr, dst, offset, size);
 771             length -= size;
 772             srcAddr += size;
 773             offset += size;
 774         }
 775     }
 776 
 777     static void copyFromCharArray(Object src, long srcPos, long dstAddr,
 778                                   long length)
 779     {
 780         copyFromShortArray(src, srcPos, dstAddr, length);
 781     }
 782 
 783     static void copyToCharArray(long srcAddr, Object dst, long dstPos,
 784                                 long length)
 785     {
 786         copyToShortArray(srcAddr, dst, dstPos, length);
 787     }
 788 
 789     static native void copyFromShortArray(Object src, long srcPos, long dstAddr,
 790                                           long length);
 791     static native void copyToShortArray(long srcAddr, Object dst, long dstPos,
 792                                         long length);
 793 
 794     static native void copyFromIntArray(Object src, long srcPos, long dstAddr,
 795                                         long length);
 796     static native void copyToIntArray(long srcAddr, Object dst, long dstPos,
 797                                         long length);
 798 
 799     static native void copyFromLongArray(Object src, long srcPos, long dstAddr,
 800                                          long length);
 801     static native void copyToLongArray(long srcAddr, Object dst, long dstPos,
 802                                        long length);
 803 
 804 }