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