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