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