View Javadoc
1   /*
2    * Copyright 2012 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.CleanableDirectBuffer;
19  import io.netty.util.internal.PlatformDependent;
20  import io.netty.util.internal.UnstableApi;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.nio.ByteBuffer;
26  
27  /**
28   * A NIO {@link ByteBuffer} based buffer. It is recommended to use
29   * {@link UnpooledByteBufAllocator#directBuffer(int, int)}, {@link Unpooled#directBuffer(int)} and
30   * {@link Unpooled#wrappedBuffer(ByteBuffer)} instead of calling the constructor explicitly.}
31   */
32  public class UnpooledUnsafeDirectByteBuf extends UnpooledDirectByteBuf {
33  
34      private static final boolean USE_VAR_HANDLE = PlatformDependent.useVarHandleForMultiByteAccess();
35  
36      long memoryAddress;
37  
38      /**
39       * Creates a new direct buffer.
40       *
41       * @param initialCapacity the initial capacity of the underlying direct buffer
42       * @param maxCapacity     the maximum capacity of the underlying direct buffer
43       */
44      public UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
45          super(alloc, initialCapacity, maxCapacity);
46      }
47  
48      UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity,
49                                  boolean permitExpensiveClean) {
50          super(alloc, initialCapacity, maxCapacity, permitExpensiveClean);
51      }
52  
53      /**
54       * Creates a new direct buffer by wrapping the specified initial buffer.
55       *
56       * @param maxCapacity the maximum capacity of the underlying direct buffer
57       */
58      protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) {
59          // We never try to free the buffer if it was provided by the end-user as we don't know if this is a duplicate or
60          // a slice. This is done to prevent an IllegalArgumentException when using Java9 as Unsafe.invokeCleaner(...)
61          // will check if the given buffer is either a duplicate or slice and in this case throw an
62          // IllegalArgumentException.
63          //
64          // See https://hg.openjdk.java.net/jdk9/hs-demo/jdk/file/0d2ab72ba600/src/jdk.unsupported/share/classes/
65          // sun/misc/Unsafe.java#l1250
66          //
67          // We also call slice() explicitly here to preserve behaviour with previous netty releases.
68          super(alloc, initialBuffer, maxCapacity, /* doFree = */ false, /* slice = */ true);
69      }
70  
71      /**
72       * Creates a new direct ByteBuf by wrapping the specified initial buffer.
73       * Allows subclasses to control if initialBuffer.slice() should be invoked.
74       *
75       *  Attention: this is a dangerous API and should only be used by someone
76       *  who really knows the possible consequences.
77       *  It allows to disable a protective slicing for the provided ByteBuffer instance
78       *  and can cause sharing of this ByteBuffer instance between several UnpooledUnsafeDirectByteBuf objects,
79       *  as a result modifications would be racy and unsafe.
80       *
81       * @param slice true means slice() should be called for the provided initialBuffer
82       * @param maxCapacity the maximum capacity of the underlying direct buffer
83       */
84      @UnstableApi
85      protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, boolean slice,
86                                            ByteBuffer initialBuffer, int maxCapacity) {
87          super(alloc, initialBuffer, maxCapacity, /* doFree = */ false, slice);
88      }
89  
90      UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity, boolean doFree) {
91          super(alloc, initialBuffer, maxCapacity, doFree, false);
92      }
93  
94      @Override
95      final void setByteBuffer(ByteBuffer buffer, boolean tryFree) {
96          super.setByteBuffer(buffer, tryFree);
97          memoryAddress = PlatformDependent.directBufferAddress(buffer);
98      }
99  
100     @Override
101     final void setByteBuffer(CleanableDirectBuffer cleanableDirectBuffer, boolean tryFree) {
102         super.setByteBuffer(cleanableDirectBuffer, tryFree);
103         memoryAddress = PlatformDependent.directBufferAddress(cleanableDirectBuffer.buffer());
104     }
105 
106     @Override
107     public boolean hasMemoryAddress() {
108         return true;
109     }
110 
111     @Override
112     public long memoryAddress() {
113         ensureAccessible();
114         return memoryAddress;
115     }
116 
117     @Override
118     public byte getByte(int index) {
119         checkIndex(index);
120         return _getByte(index);
121     }
122 
123     @Override
124     protected byte _getByte(int index) {
125         return UnsafeByteBufUtil.getByte(addr(index));
126     }
127 
128     @Override
129     public short getShort(int index) {
130         checkIndex(index, 2);
131         return _getShort(index);
132     }
133 
134     @Override
135     protected short _getShort(int index) {
136         if (USE_VAR_HANDLE) {
137             return VarHandleByteBufferAccess.getShortBE(buffer, index);
138         }
139         return UnsafeByteBufUtil.getShort(addr(index));
140     }
141 
142     @Override
143     protected short _getShortLE(int index) {
144         if (USE_VAR_HANDLE) {
145             return VarHandleByteBufferAccess.getShortLE(buffer, index);
146         }
147         return UnsafeByteBufUtil.getShortLE(addr(index));
148     }
149 
150     @Override
151     public int getUnsignedMedium(int index) {
152         checkIndex(index, 3);
153         return _getUnsignedMedium(index);
154     }
155 
156     @Override
157     protected int _getUnsignedMedium(int index) {
158         return UnsafeByteBufUtil.getUnsignedMedium(addr(index));
159     }
160 
161     @Override
162     protected int _getUnsignedMediumLE(int index) {
163         return UnsafeByteBufUtil.getUnsignedMediumLE(addr(index));
164     }
165 
166     @Override
167     public int getInt(int index) {
168         checkIndex(index, 4);
169         return _getInt(index);
170     }
171 
172     @Override
173     protected int _getInt(int index) {
174         if (USE_VAR_HANDLE) {
175             return VarHandleByteBufferAccess.getIntBE(buffer, index);
176         }
177         return UnsafeByteBufUtil.getInt(addr(index));
178     }
179 
180     @Override
181     protected int _getIntLE(int index) {
182         if (USE_VAR_HANDLE) {
183             return VarHandleByteBufferAccess.getIntLE(buffer, index);
184         }
185         return UnsafeByteBufUtil.getIntLE(addr(index));
186     }
187 
188     @Override
189     public long getLong(int index) {
190         checkIndex(index, 8);
191         return _getLong(index);
192     }
193 
194     @Override
195     protected long _getLong(int index) {
196         if (USE_VAR_HANDLE) {
197             return VarHandleByteBufferAccess.getLongBE(buffer, index);
198         }
199         return UnsafeByteBufUtil.getLong(addr(index));
200     }
201 
202     @Override
203     protected long _getLongLE(int index) {
204         if (USE_VAR_HANDLE) {
205             return VarHandleByteBufferAccess.getLongLE(buffer, index);
206         }
207         return UnsafeByteBufUtil.getLongLE(addr(index));
208     }
209 
210     @Override
211     public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
212         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
213         return this;
214     }
215 
216     @Override
217     void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) {
218         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
219     }
220 
221     @Override
222     void getBytes(int index, ByteBuffer dst, boolean internal) {
223         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst);
224     }
225 
226     @Override
227     public ByteBuf setByte(int index, int value) {
228         checkIndex(index);
229         _setByte(index, value);
230         return this;
231     }
232 
233     @Override
234     protected void _setByte(int index, int value) {
235         UnsafeByteBufUtil.setByte(addr(index), value);
236     }
237 
238     @Override
239     public ByteBuf setShort(int index, int value) {
240         checkIndex(index, 2);
241         _setShort(index, value);
242         return this;
243     }
244 
245     @Override
246     protected void _setShort(int index, int value) {
247         if (USE_VAR_HANDLE) {
248             VarHandleByteBufferAccess.setShortBE(buffer, index, value);
249             return;
250         }
251         UnsafeByteBufUtil.setShort(addr(index), value);
252     }
253 
254     @Override
255     protected void _setShortLE(int index, int value) {
256         if (USE_VAR_HANDLE) {
257             VarHandleByteBufferAccess.setShortLE(buffer, index, value);
258             return;
259         }
260         UnsafeByteBufUtil.setShortLE(addr(index), value);
261     }
262 
263     @Override
264     public ByteBuf setMedium(int index, int value) {
265         checkIndex(index, 3);
266         _setMedium(index, value);
267         return this;
268     }
269 
270     @Override
271     protected void _setMedium(int index, int value) {
272         UnsafeByteBufUtil.setMedium(addr(index), value);
273     }
274 
275     @Override
276     protected void _setMediumLE(int index, int value) {
277         UnsafeByteBufUtil.setMediumLE(addr(index), value);
278     }
279 
280     @Override
281     public ByteBuf setInt(int index, int value) {
282         checkIndex(index, 4);
283         _setInt(index, value);
284         return this;
285     }
286 
287     @Override
288     protected void _setInt(int index, int value) {
289         if (USE_VAR_HANDLE) {
290             VarHandleByteBufferAccess.setIntBE(buffer, index, value);
291             return;
292         }
293         UnsafeByteBufUtil.setInt(addr(index), value);
294     }
295 
296     @Override
297     protected void _setIntLE(int index, int value) {
298         if (USE_VAR_HANDLE) {
299             VarHandleByteBufferAccess.setIntLE(buffer, index, value);
300             return;
301         }
302         UnsafeByteBufUtil.setIntLE(addr(index), value);
303     }
304 
305     @Override
306     public ByteBuf setLong(int index, long value) {
307         checkIndex(index, 8);
308         _setLong(index, value);
309         return this;
310     }
311 
312     @Override
313     protected void _setLong(int index, long value) {
314         if (USE_VAR_HANDLE) {
315             VarHandleByteBufferAccess.setLongBE(buffer, index, value);
316             return;
317         }
318         UnsafeByteBufUtil.setLong(addr(index), value);
319     }
320 
321     @Override
322     protected void _setLongLE(int index, long value) {
323         if (USE_VAR_HANDLE) {
324             VarHandleByteBufferAccess.setLongLE(buffer, index, value);
325             return;
326         }
327         UnsafeByteBufUtil.setLongLE(addr(index), value);
328     }
329 
330     @Override
331     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
332         UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
333         return this;
334     }
335 
336     @Override
337     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
338         UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
339         return this;
340     }
341 
342     @Override
343     public ByteBuf setBytes(int index, ByteBuffer src) {
344         UnsafeByteBufUtil.setBytes(this, addr(index), index, src);
345         return this;
346     }
347 
348     @Override
349     void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException {
350         UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length);
351     }
352 
353     @Override
354     public int setBytes(int index, InputStream in, int length) throws IOException {
355         return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length);
356     }
357 
358     @Override
359     public ByteBuf copy(int index, int length) {
360         return UnsafeByteBufUtil.copy(this, addr(index), index, length);
361     }
362 
363     final long addr(int index) {
364         return memoryAddress + index;
365     }
366 
367     @Override
368     protected SwappedByteBuf newSwappedByteBuf() {
369         if (PlatformDependent.isUnaligned()) {
370             // Only use if unaligned access is supported otherwise there is no gain.
371             return new UnsafeDirectSwappedByteBuf(this);
372         }
373         return super.newSwappedByteBuf();
374     }
375 
376     @Override
377     public ByteBuf setZero(int index, int length) {
378         checkIndex(index, length);
379         UnsafeByteBufUtil.setZero(addr(index), length);
380         return this;
381     }
382 
383     @Override
384     public ByteBuf writeZero(int length) {
385         ensureWritable(length);
386         int wIndex = writerIndex;
387         UnsafeByteBufUtil.setZero(addr(wIndex), length);
388         writerIndex = wIndex + length;
389         return this;
390     }
391 }