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