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