1
25
26
27
28 package java.nio;
29
30 import java.io.FileDescriptor;
31 import java.lang.ref.Reference;
32 import jdk.internal.misc.VM;
33 import jdk.internal.ref.Cleaner;
34 import sun.nio.ch.DirectBuffer;
35
36
37 class DirectByteBuffer
38
39 extends MappedByteBuffer
40
41
42
43 implements DirectBuffer
44 {
45
46
47
48
49 private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
50
51
52 protected static final boolean UNALIGNED = Bits.unaligned();
53
54
55
56
57
58
59
60
61 private final Object att;
62
63 public Object attachment() {
64 return att;
65 }
66
67
68
69 private static class Deallocator
70 implements Runnable
71 {
72
73 private long address;
74 private long size;
75 private int capacity;
76
77 private Deallocator(long address, long size, int capacity) {
78 assert (address != 0);
79 this.address = address;
80 this.size = size;
81 this.capacity = capacity;
82 }
83
84 public void run() {
85 if (address == 0) {
86
87 return;
88 }
89 UNSAFE.freeMemory(address);
90 address = 0;
91 Bits.unreserveMemory(size, capacity);
92 }
93
94 }
95
96 private final Cleaner cleaner;
97
98 public Cleaner cleaner() { return cleaner; }
99
100
101
102
103
104
105
106
107
108
109
110
111
112 DirectByteBuffer(int cap) {
113
114 super(-1, 0, cap, cap);
115 boolean pa = VM.isDirectMemoryPageAligned();
116 int ps = Bits.pageSize();
117 long size = Math.max(1L, (long)cap + (pa ? ps : 0));
118 Bits.reserveMemory(size, cap);
119
120 long base = 0;
121 try {
122 base = UNSAFE.allocateMemory(size);
123 } catch (OutOfMemoryError x) {
124 Bits.unreserveMemory(size, cap);
125 throw x;
126 }
127 UNSAFE.setMemory(base, size, (byte) 0);
128 if (pa && (base % ps != 0)) {
129
130 address = base + ps - (base & (ps - 1));
131 } else {
132 address = base;
133 }
134 cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
135 att = null;
136
137
138
139
140 }
141
142
143
144
145
146
147 DirectByteBuffer(long addr, int cap, Object ob) {
148 super(-1, 0, cap, cap);
149 address = addr;
150 cleaner = null;
151 att = ob;
152 }
153
154
155
156
157 private DirectByteBuffer(long addr, int cap) {
158 super(-1, 0, cap, cap);
159 address = addr;
160 cleaner = null;
161 att = null;
162 }
163
164
165
166
167
168 protected DirectByteBuffer(int cap, long addr,
169 FileDescriptor fd,
170 Runnable unmapper)
171 {
172
173 super(-1, 0, cap, cap, fd);
174 address = addr;
175 cleaner = Cleaner.create(this, unmapper);
176 att = null;
177
178
179
180
181 }
182
183
184
185
186
187 DirectByteBuffer(DirectBuffer db,
188 int mark, int pos, int lim, int cap,
189 int off)
190 {
191
192 super(mark, pos, lim, cap);
193 address = db.address() + off;
194
195 cleaner = null;
196
197 att = db;
198
199
200
201
202 }
203
204 @Override
205 Object base() {
206 return null;
207 }
208
209 public ByteBuffer slice() {
210 int pos = this.position();
211 int lim = this.limit();
212 assert (pos <= lim);
213 int rem = (pos <= lim ? lim - pos : 0);
214 int off = (pos << 0);
215 assert (off >= 0);
216 return new DirectByteBuffer(this, -1, 0, rem, rem, off);
217 }
218
219
220 public ByteBuffer slice(int pos, int lim) {
221 assert (pos >= 0);
222 assert (pos <= lim);
223 int rem = lim - pos;
224 return new DirectByteBuffer(this, -1, 0, rem, rem, pos);
225 }
226
227
228 public ByteBuffer duplicate() {
229 return new DirectByteBuffer(this,
230 this.markValue(),
231 this.position(),
232 this.limit(),
233 this.capacity(),
234 0);
235 }
236
237 public ByteBuffer asReadOnlyBuffer() {
238
239 return new DirectByteBufferR(this,
240 this.markValue(),
241 this.position(),
242 this.limit(),
243 this.capacity(),
244 0);
245
246
247
248 }
249
250
251
252 public long address() {
253 return address;
254 }
255
256 private long ix(int i) {
257 return address + ((long)i << 0);
258 }
259
260 public byte get() {
261 try {
262 return ((UNSAFE.getByte(ix(nextGetIndex()))));
263 } finally {
264 Reference.reachabilityFence(this);
265 }
266 }
267
268 public byte get(int i) {
269 try {
270 return ((UNSAFE.getByte(ix(checkIndex(i)))));
271 } finally {
272 Reference.reachabilityFence(this);
273 }
274 }
275
276
277
278
279
280
281
282
283
284
285
286 public ByteBuffer get(byte[] dst, int offset, int length) {
287
288 if (((long)length << 0) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
289 checkBounds(offset, length, dst.length);
290 int pos = position();
291 int lim = limit();
292 assert (pos <= lim);
293 int rem = (pos <= lim ? lim - pos : 0);
294 if (length > rem)
295 throw new BufferUnderflowException();
296
297 long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << 0);
298 try {
299
300
301
302
303
304
305
306
307
308
309 UNSAFE.copyMemory(null,
310 ix(pos),
311 dst,
312 dstOffset,
313 (long)length << 0);
314 } finally {
315 Reference.reachabilityFence(this);
316 }
317 position(pos + length);
318 } else {
319 super.get(dst, offset, length);
320 }
321 return this;
322
323
324
325 }
326
327
328
329 public ByteBuffer put(byte x) {
330
331 try {
332 UNSAFE.putByte(ix(nextPutIndex()), ((x)));
333 } finally {
334 Reference.reachabilityFence(this);
335 }
336 return this;
337
338
339
340 }
341
342 public ByteBuffer put(int i, byte x) {
343
344 try {
345 UNSAFE.putByte(ix(checkIndex(i)), ((x)));
346 } finally {
347 Reference.reachabilityFence(this);
348 }
349 return this;
350
351
352
353 }
354
355 public ByteBuffer put(ByteBuffer src) {
356
357 if (src instanceof DirectByteBuffer) {
358 if (src == this)
359 throw createSameBufferException();
360 DirectByteBuffer sb = (DirectByteBuffer)src;
361
362 int spos = sb.position();
363 int slim = sb.limit();
364 assert (spos <= slim);
365 int srem = (spos <= slim ? slim - spos : 0);
366
367 int pos = position();
368 int lim = limit();
369 assert (pos <= lim);
370 int rem = (pos <= lim ? lim - pos : 0);
371
372 if (srem > rem)
373 throw new BufferOverflowException();
374 try {
375 UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << 0);
376 } finally {
377 Reference.reachabilityFence(sb);
378 Reference.reachabilityFence(this);
379 }
380 sb.position(spos + srem);
381 position(pos + srem);
382 } else if (src.hb != null) {
383
384 int spos = src.position();
385 int slim = src.limit();
386 assert (spos <= slim);
387 int srem = (spos <= slim ? slim - spos : 0);
388
389 put(src.hb, src.offset + spos, srem);
390 src.position(spos + srem);
391
392 } else {
393 super.put(src);
394 }
395 return this;
396
397
398
399 }
400
401 public ByteBuffer put(byte[] src, int offset, int length) {
402
403 if (((long)length << 0) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
404 checkBounds(offset, length, src.length);
405 int pos = position();
406 int lim = limit();
407 assert (pos <= lim);
408 int rem = (pos <= lim ? lim - pos : 0);
409 if (length > rem)
410 throw new BufferOverflowException();
411
412 long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << 0);
413 try {
414
415
416
417
418
419
420
421
422
423
424 UNSAFE.copyMemory(src,
425 srcOffset,
426 null,
427 ix(pos),
428 (long)length << 0);
429 } finally {
430 Reference.reachabilityFence(this);
431 }
432 position(pos + length);
433 } else {
434 super.put(src, offset, length);
435 }
436 return this;
437
438
439
440 }
441
442 public ByteBuffer compact() {
443
444 int pos = position();
445 int lim = limit();
446 assert (pos <= lim);
447 int rem = (pos <= lim ? lim - pos : 0);
448 try {
449 UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << 0);
450 } finally {
451 Reference.reachabilityFence(this);
452 }
453 position(rem);
454 limit(capacity());
455 discardMark();
456 return this;
457
458
459
460 }
461
462 public boolean isDirect() {
463 return true;
464 }
465
466 public boolean isReadOnly() {
467 return false;
468 }
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540 private char getChar(long a) {
541 try {
542 char x = UNSAFE.getCharUnaligned(null, a, bigEndian);
543 return (x);
544 } finally {
545 Reference.reachabilityFence(this);
546 }
547 }
548
549 public char getChar() {
550 try {
551 return getChar(ix(nextGetIndex((1 << 1))));
552 } finally {
553 Reference.reachabilityFence(this);
554 }
555 }
556
557 public char getChar(int i) {
558 try {
559 return getChar(ix(checkIndex(i, (1 << 1))));
560 } finally {
561 Reference.reachabilityFence(this);
562 }
563 }
564
565
566
567 private ByteBuffer putChar(long a, char x) {
568
569 try {
570 char y = (x);
571 UNSAFE.putCharUnaligned(null, a, y, bigEndian);
572 } finally {
573 Reference.reachabilityFence(this);
574 }
575 return this;
576
577
578
579 }
580
581 public ByteBuffer putChar(char x) {
582
583 putChar(ix(nextPutIndex((1 << 1))), x);
584 return this;
585
586
587
588 }
589
590 public ByteBuffer putChar(int i, char x) {
591
592 putChar(ix(checkIndex(i, (1 << 1))), x);
593 return this;
594
595
596
597 }
598
599 public CharBuffer asCharBuffer() {
600 int off = this.position();
601 int lim = this.limit();
602 assert (off <= lim);
603 int rem = (off <= lim ? lim - off : 0);
604
605 int size = rem >> 1;
606 if (!UNALIGNED && ((address + off) % (1 << 1) != 0)) {
607 return (bigEndian
608 ? (CharBuffer)(new ByteBufferAsCharBufferB(this,
609 -1,
610 0,
611 size,
612 size,
613 address + off))
614 : (CharBuffer)(new ByteBufferAsCharBufferL(this,
615 -1,
616 0,
617 size,
618 size,
619 address + off)));
620 } else {
621 return (nativeByteOrder
622 ? (CharBuffer)(new DirectCharBufferU(this,
623 -1,
624 0,
625 size,
626 size,
627 off))
628 : (CharBuffer)(new DirectCharBufferS(this,
629 -1,
630 0,
631 size,
632 size,
633 off)));
634 }
635 }
636
637
638
639
640 private short getShort(long a) {
641 try {
642 short x = UNSAFE.getShortUnaligned(null, a, bigEndian);
643 return (x);
644 } finally {
645 Reference.reachabilityFence(this);
646 }
647 }
648
649 public short getShort() {
650 try {
651 return getShort(ix(nextGetIndex((1 << 1))));
652 } finally {
653 Reference.reachabilityFence(this);
654 }
655 }
656
657 public short getShort(int i) {
658 try {
659 return getShort(ix(checkIndex(i, (1 << 1))));
660 } finally {
661 Reference.reachabilityFence(this);
662 }
663 }
664
665
666
667 private ByteBuffer putShort(long a, short x) {
668
669 try {
670 short y = (x);
671 UNSAFE.putShortUnaligned(null, a, y, bigEndian);
672 } finally {
673 Reference.reachabilityFence(this);
674 }
675 return this;
676
677
678
679 }
680
681 public ByteBuffer putShort(short x) {
682
683 putShort(ix(nextPutIndex((1 << 1))), x);
684 return this;
685
686
687
688 }
689
690 public ByteBuffer putShort(int i, short x) {
691
692 putShort(ix(checkIndex(i, (1 << 1))), x);
693 return this;
694
695
696
697 }
698
699 public ShortBuffer asShortBuffer() {
700 int off = this.position();
701 int lim = this.limit();
702 assert (off <= lim);
703 int rem = (off <= lim ? lim - off : 0);
704
705 int size = rem >> 1;
706 if (!UNALIGNED && ((address + off) % (1 << 1) != 0)) {
707 return (bigEndian
708 ? (ShortBuffer)(new ByteBufferAsShortBufferB(this,
709 -1,
710 0,
711 size,
712 size,
713 address + off))
714 : (ShortBuffer)(new ByteBufferAsShortBufferL(this,
715 -1,
716 0,
717 size,
718 size,
719 address + off)));
720 } else {
721 return (nativeByteOrder
722 ? (ShortBuffer)(new DirectShortBufferU(this,
723 -1,
724 0,
725 size,
726 size,
727 off))
728 : (ShortBuffer)(new DirectShortBufferS(this,
729 -1,
730 0,
731 size,
732 size,
733 off)));
734 }
735 }
736
737
738
739
740 private int getInt(long a) {
741 try {
742 int x = UNSAFE.getIntUnaligned(null, a, bigEndian);
743 return (x);
744 } finally {
745 Reference.reachabilityFence(this);
746 }
747 }
748
749 public int getInt() {
750 try {
751 return getInt(ix(nextGetIndex((1 << 2))));
752 } finally {
753 Reference.reachabilityFence(this);
754 }
755 }
756
757 public int getInt(int i) {
758 try {
759 return getInt(ix(checkIndex(i, (1 << 2))));
760 } finally {
761 Reference.reachabilityFence(this);
762 }
763 }
764
765
766
767 private ByteBuffer putInt(long a, int x) {
768
769 try {
770 int y = (x);
771 UNSAFE.putIntUnaligned(null, a, y, bigEndian);
772 } finally {
773 Reference.reachabilityFence(this);
774 }
775 return this;
776
777
778
779 }
780
781 public ByteBuffer putInt(int x) {
782
783 putInt(ix(nextPutIndex((1 << 2))), x);
784 return this;
785
786
787
788 }
789
790 public ByteBuffer putInt(int i, int x) {
791
792 putInt(ix(checkIndex(i, (1 << 2))), x);
793 return this;
794
795
796
797 }
798
799 public IntBuffer asIntBuffer() {
800 int off = this.position();
801 int lim = this.limit();
802 assert (off <= lim);
803 int rem = (off <= lim ? lim - off : 0);
804
805 int size = rem >> 2;
806 if (!UNALIGNED && ((address + off) % (1 << 2) != 0)) {
807 return (bigEndian
808 ? (IntBuffer)(new ByteBufferAsIntBufferB(this,
809 -1,
810 0,
811 size,
812 size,
813 address + off))
814 : (IntBuffer)(new ByteBufferAsIntBufferL(this,
815 -1,
816 0,
817 size,
818 size,
819 address + off)));
820 } else {
821 return (nativeByteOrder
822 ? (IntBuffer)(new DirectIntBufferU(this,
823 -1,
824 0,
825 size,
826 size,
827 off))
828 : (IntBuffer)(new DirectIntBufferS(this,
829 -1,
830 0,
831 size,
832 size,
833 off)));
834 }
835 }
836
837
838
839
840 private long getLong(long a) {
841 try {
842 long x = UNSAFE.getLongUnaligned(null, a, bigEndian);
843 return (x);
844 } finally {
845 Reference.reachabilityFence(this);
846 }
847 }
848
849 public long getLong() {
850 try {
851 return getLong(ix(nextGetIndex((1 << 3))));
852 } finally {
853 Reference.reachabilityFence(this);
854 }
855 }
856
857 public long getLong(int i) {
858 try {
859 return getLong(ix(checkIndex(i, (1 << 3))));
860 } finally {
861 Reference.reachabilityFence(this);
862 }
863 }
864
865
866
867 private ByteBuffer putLong(long a, long x) {
868
869 try {
870 long y = (x);
871 UNSAFE.putLongUnaligned(null, a, y, bigEndian);
872 } finally {
873 Reference.reachabilityFence(this);
874 }
875 return this;
876
877
878
879 }
880
881 public ByteBuffer putLong(long x) {
882
883 putLong(ix(nextPutIndex((1 << 3))), x);
884 return this;
885
886
887
888 }
889
890 public ByteBuffer putLong(int i, long x) {
891
892 putLong(ix(checkIndex(i, (1 << 3))), x);
893 return this;
894
895
896
897 }
898
899 public LongBuffer asLongBuffer() {
900 int off = this.position();
901 int lim = this.limit();
902 assert (off <= lim);
903 int rem = (off <= lim ? lim - off : 0);
904
905 int size = rem >> 3;
906 if (!UNALIGNED && ((address + off) % (1 << 3) != 0)) {
907 return (bigEndian
908 ? (LongBuffer)(new ByteBufferAsLongBufferB(this,
909 -1,
910 0,
911 size,
912 size,
913 address + off))
914 : (LongBuffer)(new ByteBufferAsLongBufferL(this,
915 -1,
916 0,
917 size,
918 size,
919 address + off)));
920 } else {
921 return (nativeByteOrder
922 ? (LongBuffer)(new DirectLongBufferU(this,
923 -1,
924 0,
925 size,
926 size,
927 off))
928 : (LongBuffer)(new DirectLongBufferS(this,
929 -1,
930 0,
931 size,
932 size,
933 off)));
934 }
935 }
936
937
938
939
940 private float getFloat(long a) {
941 try {
942 int x = UNSAFE.getIntUnaligned(null, a, bigEndian);
943 return Float.intBitsToFloat(x);
944 } finally {
945 Reference.reachabilityFence(this);
946 }
947 }
948
949 public float getFloat() {
950 try {
951 return getFloat(ix(nextGetIndex((1 << 2))));
952 } finally {
953 Reference.reachabilityFence(this);
954 }
955 }
956
957 public float getFloat(int i) {
958 try {
959 return getFloat(ix(checkIndex(i, (1 << 2))));
960 } finally {
961 Reference.reachabilityFence(this);
962 }
963 }
964
965
966
967 private ByteBuffer putFloat(long a, float x) {
968
969 try {
970 int y = Float.floatToRawIntBits(x);
971 UNSAFE.putIntUnaligned(null, a, y, bigEndian);
972 } finally {
973 Reference.reachabilityFence(this);
974 }
975 return this;
976
977
978
979 }
980
981 public ByteBuffer putFloat(float x) {
982
983 putFloat(ix(nextPutIndex((1 << 2))), x);
984 return this;
985
986
987
988 }
989
990 public ByteBuffer putFloat(int i, float x) {
991
992 putFloat(ix(checkIndex(i, (1 << 2))), x);
993 return this;
994
995
996
997 }
998
999 public FloatBuffer asFloatBuffer() {
1000 int off = this.position();
1001 int lim = this.limit();
1002 assert (off <= lim);
1003 int rem = (off <= lim ? lim - off : 0);
1004
1005 int size = rem >> 2;
1006 if (!UNALIGNED && ((address + off) % (1 << 2) != 0)) {
1007 return (bigEndian
1008 ? (FloatBuffer)(new ByteBufferAsFloatBufferB(this,
1009 -1,
1010 0,
1011 size,
1012 size,
1013 address + off))
1014 : (FloatBuffer)(new ByteBufferAsFloatBufferL(this,
1015 -1,
1016 0,
1017 size,
1018 size,
1019 address + off)));
1020 } else {
1021 return (nativeByteOrder
1022 ? (FloatBuffer)(new DirectFloatBufferU(this,
1023 -1,
1024 0,
1025 size,
1026 size,
1027 off))
1028 : (FloatBuffer)(new DirectFloatBufferS(this,
1029 -1,
1030 0,
1031 size,
1032 size,
1033 off)));
1034 }
1035 }
1036
1037
1038
1039
1040 private double getDouble(long a) {
1041 try {
1042 long x = UNSAFE.getLongUnaligned(null, a, bigEndian);
1043 return Double.longBitsToDouble(x);
1044 } finally {
1045 Reference.reachabilityFence(this);
1046 }
1047 }
1048
1049 public double getDouble() {
1050 try {
1051 return getDouble(ix(nextGetIndex((1 << 3))));
1052 } finally {
1053 Reference.reachabilityFence(this);
1054 }
1055 }
1056
1057 public double getDouble(int i) {
1058 try {
1059 return getDouble(ix(checkIndex(i, (1 << 3))));
1060 } finally {
1061 Reference.reachabilityFence(this);
1062 }
1063 }
1064
1065
1066
1067 private ByteBuffer putDouble(long a, double x) {
1068
1069 try {
1070 long y = Double.doubleToRawLongBits(x);
1071 UNSAFE.putLongUnaligned(null, a, y, bigEndian);
1072 } finally {
1073 Reference.reachabilityFence(this);
1074 }
1075 return this;
1076
1077
1078
1079 }
1080
1081 public ByteBuffer putDouble(double x) {
1082
1083 putDouble(ix(nextPutIndex((1 << 3))), x);
1084 return this;
1085
1086
1087
1088 }
1089
1090 public ByteBuffer putDouble(int i, double x) {
1091
1092 putDouble(ix(checkIndex(i, (1 << 3))), x);
1093 return this;
1094
1095
1096
1097 }
1098
1099 public DoubleBuffer asDoubleBuffer() {
1100 int off = this.position();
1101 int lim = this.limit();
1102 assert (off <= lim);
1103 int rem = (off <= lim ? lim - off : 0);
1104
1105 int size = rem >> 3;
1106 if (!UNALIGNED && ((address + off) % (1 << 3) != 0)) {
1107 return (bigEndian
1108 ? (DoubleBuffer)(new ByteBufferAsDoubleBufferB(this,
1109 -1,
1110 0,
1111 size,
1112 size,
1113 address + off))
1114 : (DoubleBuffer)(new ByteBufferAsDoubleBufferL(this,
1115 -1,
1116 0,
1117 size,
1118 size,
1119 address + off)));
1120 } else {
1121 return (nativeByteOrder
1122 ? (DoubleBuffer)(new DirectDoubleBufferU(this,
1123 -1,
1124 0,
1125 size,
1126 size,
1127 off))
1128 : (DoubleBuffer)(new DirectDoubleBufferS(this,
1129 -1,
1130 0,
1131 size,
1132 size,
1133 off)));
1134 }
1135 }
1136
1137 }
1138