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