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