View Javadoc
1   /*
2    * Copyright 2015 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.buffer;
17  
18  import io.netty.util.internal.PlatformDependent;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.nio.ByteBuffer;
24  import java.nio.ByteOrder;
25  import java.nio.ReadOnlyBufferException;
26  
27  import static io.netty.util.internal.MathUtil.isOutOfBounds;
28  import static io.netty.util.internal.ObjectUtil.checkNotNull;
29  import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
30  
31  /**
32   * All operations get and set as {@link ByteOrder#BIG_ENDIAN}.
33   */
34  final class UnsafeByteBufUtil {
35      private static final boolean UNALIGNED = PlatformDependent.isUnaligned();
36      private static final boolean USE_VAR_HANDLE = PlatformDependent.useVarHandleForMultiByteAccess();
37      private static final byte ZERO = 0;
38      private static final int MAX_HAND_ROLLED_SET_ZERO_BYTES = 64;
39  
40      static byte getByte(long address) {
41          return PlatformDependent.getByte(address);
42      }
43  
44      static short getShort(long address) {
45          if (UNALIGNED) {
46              short v = PlatformDependent.getShort(address);
47              return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
48          }
49          return (short) (PlatformDependent.getByte(address) << 8 | PlatformDependent.getByte(address + 1) & 0xff);
50      }
51  
52      static short getShortLE(long address) {
53          if (UNALIGNED) {
54              short v = PlatformDependent.getShort(address);
55              return BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(v) : v;
56          }
57          return (short) (PlatformDependent.getByte(address) & 0xff | PlatformDependent.getByte(address + 1) << 8);
58      }
59  
60      static int getUnsignedMedium(long address) {
61          if (UNALIGNED) {
62              return (PlatformDependent.getByte(address) & 0xff) << 16 |
63                      (BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(address + 1)
64                                               : Short.reverseBytes(PlatformDependent.getShort(address + 1))) & 0xffff;
65          }
66          return (PlatformDependent.getByte(address)     & 0xff) << 16 |
67                 (PlatformDependent.getByte(address + 1) & 0xff) << 8  |
68                 PlatformDependent.getByte(address + 2)  & 0xff;
69      }
70  
71      static int getUnsignedMediumLE(long address) {
72          if (UNALIGNED) {
73              return (PlatformDependent.getByte(address) & 0xff) |
74                      ((BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(PlatformDependent.getShort(address + 1))
75                                                : PlatformDependent.getShort(address + 1)) & 0xffff) << 8;
76          }
77          return PlatformDependent.getByte(address)      & 0xff        |
78                 (PlatformDependent.getByte(address + 1) & 0xff) << 8  |
79                 (PlatformDependent.getByte(address + 2) & 0xff) << 16;
80      }
81  
82      static int getInt(long address) {
83          if (UNALIGNED) {
84              int v = PlatformDependent.getInt(address);
85              return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
86          }
87          return PlatformDependent.getByte(address) << 24 |
88                 (PlatformDependent.getByte(address + 1) & 0xff) << 16 |
89                 (PlatformDependent.getByte(address + 2) & 0xff) <<  8 |
90                 PlatformDependent.getByte(address + 3)  & 0xff;
91      }
92  
93      static int getIntLE(long address) {
94          if (UNALIGNED) {
95              int v = PlatformDependent.getInt(address);
96              return BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(v) : v;
97          }
98          return PlatformDependent.getByte(address) & 0xff |
99                 (PlatformDependent.getByte(address + 1) & 0xff) <<  8 |
100                (PlatformDependent.getByte(address + 2) & 0xff) << 16 |
101                PlatformDependent.getByte(address + 3) << 24;
102     }
103 
104     static long getLong(long address) {
105         if (UNALIGNED) {
106             long v = PlatformDependent.getLong(address);
107             return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
108         }
109         return ((long) PlatformDependent.getByte(address)) << 56 |
110                (PlatformDependent.getByte(address + 1) & 0xffL) << 48 |
111                (PlatformDependent.getByte(address + 2) & 0xffL) << 40 |
112                (PlatformDependent.getByte(address + 3) & 0xffL) << 32 |
113                (PlatformDependent.getByte(address + 4) & 0xffL) << 24 |
114                (PlatformDependent.getByte(address + 5) & 0xffL) << 16 |
115                (PlatformDependent.getByte(address + 6) & 0xffL) <<  8 |
116                (PlatformDependent.getByte(address + 7)) & 0xffL;
117     }
118 
119     static long getLongLE(long address) {
120         if (UNALIGNED) {
121             long v = PlatformDependent.getLong(address);
122             return BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(v) : v;
123         }
124         return (PlatformDependent.getByte(address))    & 0xffL        |
125                (PlatformDependent.getByte(address + 1) & 0xffL) <<  8 |
126                (PlatformDependent.getByte(address + 2) & 0xffL) << 16 |
127                (PlatformDependent.getByte(address + 3) & 0xffL) << 24 |
128                (PlatformDependent.getByte(address + 4) & 0xffL) << 32 |
129                (PlatformDependent.getByte(address + 5) & 0xffL) << 40 |
130                (PlatformDependent.getByte(address + 6) & 0xffL) << 48 |
131                ((long) PlatformDependent.getByte(address + 7))  << 56;
132     }
133 
134     static void setByte(long address, int value) {
135         PlatformDependent.putByte(address, (byte) value);
136     }
137 
138     static void setShort(long address, int value) {
139         if (UNALIGNED) {
140             PlatformDependent.putShort(
141                     address, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
142         } else {
143             PlatformDependent.putByte(address, (byte) (value >>> 8));
144             PlatformDependent.putByte(address + 1, (byte) value);
145         }
146     }
147 
148     static void setShortLE(long address, int value) {
149         if (UNALIGNED) {
150             PlatformDependent.putShort(
151                 address, BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) value) : (short) value);
152         } else {
153             PlatformDependent.putByte(address, (byte) value);
154             PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
155         }
156     }
157 
158     static void setMedium(long address, int value) {
159         PlatformDependent.putByte(address, (byte) (value >>> 16));
160         if (UNALIGNED) {
161             PlatformDependent.putShort(address + 1, BIG_ENDIAN_NATIVE_ORDER ? (short) value
162                                                                             : Short.reverseBytes((short) value));
163         } else {
164             PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
165             PlatformDependent.putByte(address + 2, (byte) value);
166         }
167     }
168 
169     static void setMediumLE(long address, int value) {
170         PlatformDependent.putByte(address, (byte) value);
171         if (UNALIGNED) {
172             PlatformDependent.putShort(address + 1, BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) (value >>> 8))
173                                                                             : (short) (value >>> 8));
174         } else {
175             PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
176             PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
177         }
178     }
179 
180     static void setInt(long address, int value) {
181         if (UNALIGNED) {
182             PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
183         } else {
184             PlatformDependent.putByte(address, (byte) (value >>> 24));
185             PlatformDependent.putByte(address + 1, (byte) (value >>> 16));
186             PlatformDependent.putByte(address + 2, (byte) (value >>> 8));
187             PlatformDependent.putByte(address + 3, (byte) value);
188         }
189     }
190 
191     static void setIntLE(long address, int value) {
192         if (UNALIGNED) {
193             PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(value) : value);
194         } else {
195             PlatformDependent.putByte(address, (byte) value);
196             PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
197             PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
198             PlatformDependent.putByte(address + 3, (byte) (value >>> 24));
199         }
200     }
201 
202     static void setLong(long address, long value) {
203         if (UNALIGNED) {
204             PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
205         } else {
206             PlatformDependent.putByte(address, (byte) (value >>> 56));
207             PlatformDependent.putByte(address + 1, (byte) (value >>> 48));
208             PlatformDependent.putByte(address + 2, (byte) (value >>> 40));
209             PlatformDependent.putByte(address + 3, (byte) (value >>> 32));
210             PlatformDependent.putByte(address + 4, (byte) (value >>> 24));
211             PlatformDependent.putByte(address + 5, (byte) (value >>> 16));
212             PlatformDependent.putByte(address + 6, (byte) (value >>> 8));
213             PlatformDependent.putByte(address + 7, (byte) value);
214         }
215     }
216 
217     static void setLongLE(long address, long value) {
218         if (UNALIGNED) {
219             PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(value) : value);
220         } else {
221             PlatformDependent.putByte(address, (byte) value);
222             PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
223             PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
224             PlatformDependent.putByte(address + 3, (byte) (value >>> 24));
225             PlatformDependent.putByte(address + 4, (byte) (value >>> 32));
226             PlatformDependent.putByte(address + 5, (byte) (value >>> 40));
227             PlatformDependent.putByte(address + 6, (byte) (value >>> 48));
228             PlatformDependent.putByte(address + 7, (byte) (value >>> 56));
229         }
230     }
231 
232     static byte getByte(byte[] array, int index) {
233         return PlatformDependent.getByte(array, index);
234     }
235 
236     static short getShort(byte[] array, int index) {
237         if (UNALIGNED) {
238             short v = PlatformDependent.getShort(array, index);
239             return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
240         }
241         if (USE_VAR_HANDLE) {
242             return VarHandleByteBufferAccess.getShortBE(array, index);
243         }
244         return (short) (PlatformDependent.getByte(array, index) << 8 |
245                        PlatformDependent.getByte(array, index + 1) & 0xff);
246     }
247 
248     static short getShortLE(byte[] array, int index) {
249         if (UNALIGNED) {
250             short v = PlatformDependent.getShort(array, index);
251             return BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(v) : v;
252         }
253         if (USE_VAR_HANDLE) {
254             return VarHandleByteBufferAccess.getShortLE(array, index);
255         }
256         return (short) (PlatformDependent.getByte(array, index) & 0xff |
257                        PlatformDependent.getByte(array, index + 1) << 8);
258     }
259 
260     static int getUnsignedMedium(byte[] array, int index) {
261         if (UNALIGNED) {
262             return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
263                     (BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(array, index + 1)
264                                              : Short.reverseBytes(PlatformDependent.getShort(array, index + 1)))
265                             & 0xffff;
266         }
267         return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
268                (PlatformDependent.getByte(array, index + 1) & 0xff) <<  8 |
269                PlatformDependent.getByte(array, index + 2) & 0xff;
270     }
271 
272     static int getUnsignedMediumLE(byte[] array, int index) {
273         if (UNALIGNED) {
274             return (PlatformDependent.getByte(array, index) & 0xff) |
275                     ((BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(PlatformDependent.getShort(array, index + 1))
276                                               : PlatformDependent.getShort(array, index + 1)) & 0xffff) << 8;
277         }
278         return PlatformDependent.getByte(array, index) & 0xff |
279                (PlatformDependent.getByte(array, index + 1) & 0xff) <<  8 |
280                (PlatformDependent.getByte(array, index + 2) & 0xff) << 16;
281     }
282 
283     static int getInt(byte[] array, int index) {
284         if (UNALIGNED) {
285             int v = PlatformDependent.getInt(array, index);
286             return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
287         }
288         if (USE_VAR_HANDLE) {
289             return VarHandleByteBufferAccess.getIntBE(array, index);
290         }
291         return PlatformDependent.getByte(array, index) << 24 |
292                (PlatformDependent.getByte(array, index + 1) & 0xff) << 16 |
293                (PlatformDependent.getByte(array, index + 2) & 0xff) <<  8 |
294                PlatformDependent.getByte(array, index + 3) & 0xff;
295     }
296 
297     static int getIntLE(byte[] array, int index) {
298         if (UNALIGNED) {
299             int v = PlatformDependent.getInt(array, index);
300             return BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(v) : v;
301         }
302         if (USE_VAR_HANDLE) {
303             return VarHandleByteBufferAccess.getIntLE(array, index);
304         }
305         return PlatformDependent.getByte(array, index)      & 0xff        |
306                (PlatformDependent.getByte(array, index + 1) & 0xff) <<  8 |
307                (PlatformDependent.getByte(array, index + 2) & 0xff) << 16 |
308                PlatformDependent.getByte(array,  index + 3) << 24;
309     }
310 
311     static long getLong(byte[] array, int index) {
312         if (UNALIGNED) {
313             long v = PlatformDependent.getLong(array, index);
314             return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
315         }
316         if (USE_VAR_HANDLE) {
317             return VarHandleByteBufferAccess.getLongBE(array, index);
318         }
319         return ((long) PlatformDependent.getByte(array, index)) << 56 |
320                (PlatformDependent.getByte(array, index + 1) & 0xffL) << 48 |
321                (PlatformDependent.getByte(array, index + 2) & 0xffL) << 40 |
322                (PlatformDependent.getByte(array, index + 3) & 0xffL) << 32 |
323                (PlatformDependent.getByte(array, index + 4) & 0xffL) << 24 |
324                (PlatformDependent.getByte(array, index + 5) & 0xffL) << 16 |
325                (PlatformDependent.getByte(array, index + 6) & 0xffL) <<  8 |
326                (PlatformDependent.getByte(array, index + 7)) & 0xffL;
327     }
328 
329     static long getLongLE(byte[] array, int index) {
330         if (UNALIGNED) {
331             long v = PlatformDependent.getLong(array, index);
332             return BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(v) : v;
333         }
334         if (USE_VAR_HANDLE) {
335             return VarHandleByteBufferAccess.getLongLE(array, index);
336         }
337         return PlatformDependent.getByte(array, index)      & 0xffL        |
338                (PlatformDependent.getByte(array, index + 1) & 0xffL) <<  8 |
339                (PlatformDependent.getByte(array, index + 2) & 0xffL) << 16 |
340                (PlatformDependent.getByte(array, index + 3) & 0xffL) << 24 |
341                (PlatformDependent.getByte(array, index + 4) & 0xffL) << 32 |
342                (PlatformDependent.getByte(array, index + 5) & 0xffL) << 40 |
343                (PlatformDependent.getByte(array, index + 6) & 0xffL) << 48 |
344                ((long) PlatformDependent.getByte(array,  index + 7)) << 56;
345     }
346 
347     static void setByte(byte[] array, int index, int value) {
348         PlatformDependent.putByte(array, index, (byte) value);
349     }
350 
351     static void setShort(byte[] array, int index, int value) {
352         if (UNALIGNED) {
353             PlatformDependent.putShort(array, index,
354                                        BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
355         } else if (USE_VAR_HANDLE) {
356             VarHandleByteBufferAccess.setShortBE(array, index, value);
357         } else {
358             PlatformDependent.putByte(array, index, (byte) (value >>> 8));
359             PlatformDependent.putByte(array, index + 1, (byte) value);
360         }
361     }
362 
363     static void setShortLE(byte[] array, int index, int value) {
364         if (UNALIGNED) {
365             PlatformDependent.putShort(array, index,
366                                        BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) value) : (short) value);
367         } else if (USE_VAR_HANDLE) {
368             VarHandleByteBufferAccess.setShortLE(array, index, value);
369         } else {
370             PlatformDependent.putByte(array, index, (byte) value);
371             PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
372         }
373     }
374 
375     static void setMedium(byte[] array, int index, int value) {
376         PlatformDependent.putByte(array, index, (byte) (value >>> 16));
377         if (UNALIGNED) {
378                 PlatformDependent.putShort(array, index + 1,
379                                            BIG_ENDIAN_NATIVE_ORDER ? (short) value
380                                                                    : Short.reverseBytes((short) value));
381         } else {
382             PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
383             PlatformDependent.putByte(array, index + 2, (byte) value);
384         }
385     }
386 
387     static void setMediumLE(byte[] array, int index, int value) {
388         PlatformDependent.putByte(array, index, (byte) value);
389         if (UNALIGNED) {
390             PlatformDependent.putShort(array, index + 1,
391                                        BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) (value >>> 8))
392                                                                : (short) (value >>> 8));
393         } else {
394             PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
395             PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
396         }
397     }
398 
399     static void setInt(byte[] array, int index, int value) {
400         if (UNALIGNED) {
401             PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
402         } else if (USE_VAR_HANDLE) {
403             VarHandleByteBufferAccess.setIntBE(array, index, value);
404         } else {
405             PlatformDependent.putByte(array, index, (byte) (value >>> 24));
406             PlatformDependent.putByte(array, index + 1, (byte) (value >>> 16));
407             PlatformDependent.putByte(array, index + 2, (byte) (value >>> 8));
408             PlatformDependent.putByte(array, index + 3, (byte) value);
409         }
410     }
411 
412     static void setIntLE(byte[] array, int index, int value) {
413         if (UNALIGNED) {
414             PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(value) : value);
415         } else if (USE_VAR_HANDLE) {
416             VarHandleByteBufferAccess.setIntLE(array, index, value);
417         } else {
418             PlatformDependent.putByte(array, index, (byte) value);
419             PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
420             PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
421             PlatformDependent.putByte(array, index + 3, (byte) (value >>> 24));
422         }
423     }
424 
425     static void setLong(byte[] array, int index, long value) {
426         if (UNALIGNED) {
427             PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
428         } else if (USE_VAR_HANDLE) {
429             VarHandleByteBufferAccess.setLongBE(array, index, value);
430         } else {
431             PlatformDependent.putByte(array, index, (byte) (value >>> 56));
432             PlatformDependent.putByte(array, index + 1, (byte) (value >>> 48));
433             PlatformDependent.putByte(array, index + 2, (byte) (value >>> 40));
434             PlatformDependent.putByte(array, index + 3, (byte) (value >>> 32));
435             PlatformDependent.putByte(array, index + 4, (byte) (value >>> 24));
436             PlatformDependent.putByte(array, index + 5, (byte) (value >>> 16));
437             PlatformDependent.putByte(array, index + 6, (byte) (value >>> 8));
438             PlatformDependent.putByte(array, index + 7, (byte) value);
439         }
440     }
441 
442     static void setLongLE(byte[] array, int index, long value) {
443         if (UNALIGNED) {
444             PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(value) : value);
445         } else if (USE_VAR_HANDLE) {
446             VarHandleByteBufferAccess.setLongLE(array, index, value);
447         } else {
448             PlatformDependent.putByte(array, index, (byte) value);
449             PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
450             PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
451             PlatformDependent.putByte(array, index + 3, (byte) (value >>> 24));
452             PlatformDependent.putByte(array, index + 4, (byte) (value >>> 32));
453             PlatformDependent.putByte(array, index + 5, (byte) (value >>> 40));
454             PlatformDependent.putByte(array, index + 6, (byte) (value >>> 48));
455             PlatformDependent.putByte(array, index + 7, (byte) (value >>> 56));
456         }
457     }
458 
459     private static void batchSetZero(byte[] data, int index, int length) {
460         int longBatches = length >>> 3;
461         for (int i = 0; i < longBatches; i++) {
462             PlatformDependent.putLong(data, index, ZERO);
463             index += 8;
464         }
465         final int remaining = length & 0x07;
466         for (int i = 0; i < remaining; i++) {
467             PlatformDependent.putByte(data, index + i, ZERO);
468         }
469     }
470 
471     static void setZero(byte[] array, int index, int length) {
472         if (length == 0) {
473             return;
474         }
475         // fast-path for small writes to avoid thread-state change JDK's handling
476         if (UNALIGNED && length <= MAX_HAND_ROLLED_SET_ZERO_BYTES) {
477             batchSetZero(array, index, length);
478         } else {
479             PlatformDependent.setMemory(array, index, length, ZERO);
480         }
481     }
482 
483     static ByteBuf copy(AbstractByteBuf buf, long addr, int index, int length) {
484         buf.checkIndex(index, length);
485         ByteBuf copy = buf.alloc().directBuffer(length, buf.maxCapacity());
486         if (length != 0) {
487             if (copy.hasMemoryAddress()) {
488                 PlatformDependent.copyMemory(addr, copy.memoryAddress(), length);
489                 copy.setIndex(0, length);
490             } else {
491                 copy.writeBytes(buf, index, length);
492             }
493         }
494         return copy;
495     }
496 
497     static int setBytes(AbstractByteBuf buf, long addr, int index, InputStream in, int length) throws IOException {
498         buf.checkIndex(index, length);
499         ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
500         try {
501             byte[] tmp = tmpBuf.array();
502             int offset = tmpBuf.arrayOffset();
503             int readBytes = in.read(tmp, offset, length);
504             if (readBytes > 0) {
505                 PlatformDependent.copyMemory(tmp, offset, addr, readBytes);
506             }
507             return readBytes;
508         } finally {
509             tmpBuf.release();
510         }
511     }
512 
513     static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuf dst, int dstIndex, int length) {
514         buf.checkIndex(index, length);
515         checkNotNull(dst, "dst");
516         if (isOutOfBounds(dstIndex, length, dst.capacity())) {
517             throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
518         }
519 
520         if (dst.hasMemoryAddress()) {
521             PlatformDependent.copyMemory(addr, dst.memoryAddress() + dstIndex, length);
522         } else if (dst.hasArray()) {
523             PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dstIndex, length);
524         } else {
525             dst.setBytes(dstIndex, buf, index, length);
526         }
527     }
528 
529     static void getBytes(AbstractByteBuf buf, long addr, int index, byte[] dst, int dstIndex, int length) {
530         buf.checkIndex(index, length);
531         checkNotNull(dst, "dst");
532         if (isOutOfBounds(dstIndex, length, dst.length)) {
533             throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
534         }
535         if (length != 0) {
536             PlatformDependent.copyMemory(addr, dst, dstIndex, length);
537         }
538     }
539 
540     static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer dst) {
541         buf.checkIndex(index, dst.remaining());
542         if (dst.remaining() == 0) {
543             return;
544         }
545 
546         if (dst.isDirect()) {
547             if (dst.isReadOnly()) {
548                 // We need to check if dst is ready-only so we not write something in it by using Unsafe.
549                 throw new ReadOnlyBufferException();
550             }
551             // Copy to direct memory
552             long dstAddress = PlatformDependent.directBufferAddress(dst);
553             PlatformDependent.copyMemory(addr, dstAddress + dst.position(), dst.remaining());
554             dst.position(dst.position() + dst.remaining());
555         } else if (dst.hasArray()) {
556             // Copy to array
557             PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), dst.remaining());
558             dst.position(dst.position() + dst.remaining());
559         } else  {
560             dst.put(buf.nioBuffer());
561         }
562     }
563 
564     static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuf src, int srcIndex, int length) {
565         buf.checkIndex(index, length);
566         checkNotNull(src, "src");
567         if (isOutOfBounds(srcIndex, length, src.capacity())) {
568             throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
569         }
570 
571         if (length != 0) {
572             if (src.hasMemoryAddress()) {
573                 PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr, length);
574             } else if (src.hasArray()) {
575                 PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr, length);
576             } else {
577                 src.getBytes(srcIndex, buf, index, length);
578             }
579         }
580     }
581 
582     static void setBytes(AbstractByteBuf buf, long addr, int index, byte[] src, int srcIndex, int length) {
583         buf.checkIndex(index, length);
584         // we need to check not null for src as it may cause the JVM crash
585         // See https://github.com/netty/netty/issues/10791
586         checkNotNull(src, "src");
587         if (isOutOfBounds(srcIndex, length, src.length)) {
588             throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
589         }
590 
591         if (length != 0) {
592             PlatformDependent.copyMemory(src, srcIndex, addr, length);
593         }
594     }
595 
596     static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer src) {
597         final int length = src.remaining();
598         if (length == 0) {
599             return;
600         }
601 
602         if (src.isDirect()) {
603             buf.checkIndex(index, length);
604             // Copy from direct memory
605             long srcAddress = PlatformDependent.directBufferAddress(src);
606             PlatformDependent.copyMemory(srcAddress + src.position(), addr, length);
607             src.position(src.position() + length);
608         } else if (src.hasArray()) {
609             buf.checkIndex(index, length);
610             // Copy from array
611             PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length);
612             src.position(src.position() + length);
613         } else {
614             if (length < 8) {
615                 setSingleBytes(buf, addr, index, src, length);
616             } else {
617                 //no need to checkIndex: internalNioBuffer is already taking care of it
618                 assert buf.nioBufferCount() == 1;
619                 final ByteBuffer internalBuffer = buf.internalNioBuffer(index, length);
620                 internalBuffer.put(src);
621             }
622         }
623     }
624 
625     private static void setSingleBytes(final AbstractByteBuf buf, final long addr, final int index,
626                                        final ByteBuffer src, final int length) {
627         buf.checkIndex(index, length);
628         final int srcPosition = src.position();
629         final int srcLimit = src.limit();
630         long dstAddr = addr;
631         for (int srcIndex = srcPosition; srcIndex < srcLimit; srcIndex++) {
632             final byte value = src.get(srcIndex);
633             PlatformDependent.putByte(dstAddr, value);
634             dstAddr++;
635         }
636         src.position(srcLimit);
637     }
638 
639     static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException {
640         buf.checkIndex(index, length);
641         if (length != 0) {
642             int len = Math.min(length, ByteBufUtil.WRITE_CHUNK_SIZE);
643             if (len <= ByteBufUtil.MAX_TL_ARRAY_LEN || !buf.alloc().isDirectBufferPooled()) {
644                 getBytes(addr, ByteBufUtil.threadLocalTempArray(len), 0, len, out, length);
645             } else {
646                 // if direct buffers are pooled chances are good that heap buffers are pooled as well.
647                 ByteBuf tmpBuf = buf.alloc().heapBuffer(len);
648                 try {
649                     byte[] tmp = tmpBuf.array();
650                     int offset = tmpBuf.arrayOffset();
651                     getBytes(addr, tmp, offset, len, out, length);
652                 } finally {
653                     tmpBuf.release();
654                 }
655             }
656         }
657     }
658 
659     private static void getBytes(long inAddr, byte[] in, int inOffset, int inLen, OutputStream out, int outLen)
660             throws IOException {
661         do {
662             int len = Math.min(inLen, outLen);
663             PlatformDependent.copyMemory(inAddr, in, inOffset, len);
664             out.write(in, inOffset, len);
665             outLen -= len;
666             inAddr += len;
667         } while (outLen > 0);
668     }
669 
670     private static void batchSetZero(long addr, int length) {
671         int longBatches = length >>> 3;
672         for (int i = 0; i < longBatches; i++) {
673             PlatformDependent.putLong(addr, ZERO);
674             addr += 8;
675         }
676         final int remaining = length & 0x07;
677         for (int i = 0; i < remaining; i++) {
678             PlatformDependent.putByte(addr + i, ZERO);
679         }
680     }
681 
682     static void setZero(long addr, int length) {
683         if (length == 0) {
684             return;
685         }
686         // fast-path for small writes to avoid thread-state change JDK's handling
687         if (length <= MAX_HAND_ROLLED_SET_ZERO_BYTES) {
688             if (!UNALIGNED) {
689                 // write bytes until the address is aligned
690                 int bytesToGetAligned = zeroTillAligned(addr, length);
691                 addr += bytesToGetAligned;
692                 length -= bytesToGetAligned;
693                 if (length == 0) {
694                     return;
695                 }
696                 assert is8BytesAligned(addr);
697             }
698             batchSetZero(addr, length);
699         } else {
700             PlatformDependent.setMemory(addr, length, ZERO);
701         }
702     }
703 
704     static long next8bytesAlignedAddr(long addr) {
705         return (addr + 7L) & ~7L;
706     }
707 
708     static boolean is8BytesAligned(long addr) {
709         return (addr & 7L) == 0;
710     }
711 
712     private static int zeroTillAligned(long addr, int length) {
713         long alignedAddr = next8bytesAlignedAddr(addr);
714         int bytesToGetAligned = (int) (alignedAddr - addr);
715         int toZero = Math.min(bytesToGetAligned, length);
716         for (int i = 0; i < toZero; i++) {
717             PlatformDependent.putByte(addr + i, ZERO);
718         }
719         return toZero;
720     }
721 
722     /**
723      * Allocates direct buffers for chunks used in the pooling allocators.
724      * @param alloc The allocator we're creating a chunk for.
725      * @param initialCapacity The initial capacity.
726      * @param maxCapacity The max capacity.
727      * @return The {@link UnpooledDirectByteBuf} with the chunk memory.
728      */
729     static UnpooledDirectByteBuf newDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
730         if (PlatformDependent.hasUnsafe()) {
731             if (PlatformDependent.useDirectBufferNoCleaner()) {
732                 return new UnpooledUnsafeNoCleanerDirectByteBuf(alloc, initialCapacity, maxCapacity);
733             }
734             return new UnpooledUnsafeDirectByteBuf(alloc, initialCapacity, maxCapacity, true);
735         }
736         return new UnpooledDirectByteBuf(alloc, initialCapacity, maxCapacity, true);
737     }
738 
739     private UnsafeByteBufUtil() { }
740 }