1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.buffer;
18
19 import io.netty.util.IllegalReferenceCountException;
20 import io.netty.util.ResourceLeakDetector;
21 import io.netty.util.ResourceLeakTracker;
22 import io.netty.util.internal.ObjectUtil;
23 import io.netty.util.internal.ThrowableUtil;
24
25 import java.nio.ByteOrder;
26
27 class SimpleLeakAwareByteBuf extends WrappedByteBuf {
28
29
30
31
32
33
34 private final ByteBuf trackedByteBuf;
35 final ResourceLeakTracker<ByteBuf> leak;
36
37 SimpleLeakAwareByteBuf(ByteBuf wrapped, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leak) {
38 super(wrapped);
39 this.trackedByteBuf = ObjectUtil.checkNotNull(trackedByteBuf, "trackedByteBuf");
40 this.leak = ObjectUtil.checkNotNull(leak, "leak");
41 }
42
43 SimpleLeakAwareByteBuf(ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leak) {
44 this(wrapped, wrapped, leak);
45 }
46
47 @Override
48 public ByteBuf slice() {
49 return newSharedLeakAwareByteBuf(super.slice());
50 }
51
52 @Override
53 public ByteBuf retainedSlice() {
54 try {
55 return unwrappedDerived(super.retainedSlice());
56 } catch (IllegalReferenceCountException irce) {
57 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
58 throw irce;
59 }
60 }
61
62 @Override
63 public ByteBuf retainedSlice(int index, int length) {
64 try {
65 return unwrappedDerived(super.retainedSlice(index, length));
66 } catch (IllegalReferenceCountException irce) {
67 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
68 throw irce;
69 }
70 }
71
72 @Override
73 public ByteBuf retainedDuplicate() {
74 try {
75 return unwrappedDerived(super.retainedDuplicate());
76 } catch (IllegalReferenceCountException irce) {
77 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
78 throw irce;
79 }
80 }
81
82 @Override
83 public ByteBuf readRetainedSlice(int length) {
84 try {
85 return unwrappedDerived(super.readRetainedSlice(length));
86 } catch (IllegalReferenceCountException irce) {
87 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
88 throw irce;
89 }
90 }
91
92 @Override
93 public ByteBuf slice(int index, int length) {
94 return newSharedLeakAwareByteBuf(super.slice(index, length));
95 }
96
97 @Override
98 public ByteBuf duplicate() {
99 return newSharedLeakAwareByteBuf(super.duplicate());
100 }
101
102 @Override
103 public ByteBuf readSlice(int length) {
104 return newSharedLeakAwareByteBuf(super.readSlice(length));
105 }
106
107 @Override
108 public ByteBuf asReadOnly() {
109 return newSharedLeakAwareByteBuf(super.asReadOnly());
110 }
111
112 @Override
113 public ByteBuf touch() {
114 return this;
115 }
116
117 @Override
118 public ByteBuf touch(Object hint) {
119 return this;
120 }
121
122 @Override
123 public ByteBuf retain() {
124 try {
125 return super.retain();
126 } catch (IllegalReferenceCountException irce) {
127 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
128 throw irce;
129 }
130 }
131
132 @Override
133 public ByteBuf retain(int increment) {
134 try {
135 return super.retain(increment);
136 } catch (IllegalReferenceCountException irce) {
137 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
138 throw irce;
139 }
140 }
141
142 @Override
143 public boolean release() {
144 try {
145 if (super.release()) {
146 closeLeak();
147 return true;
148 }
149 return false;
150 } catch (IllegalReferenceCountException irce) {
151 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
152 throw irce;
153 }
154 }
155
156 @Override
157 public boolean release(int decrement) {
158 try {
159 if (super.release(decrement)) {
160 closeLeak();
161 return true;
162 }
163 return false;
164 } catch (IllegalReferenceCountException irce) {
165 ThrowableUtil.addSuppressed(irce, leak.getCloseStackTraceIfAny());
166 throw irce;
167 }
168 }
169
170 private void closeLeak() {
171
172
173 boolean closed = leak.close(trackedByteBuf);
174 assert closed;
175 }
176
177 @Override
178 public ByteBuf order(ByteOrder endianness) {
179 if (order() == endianness) {
180 return this;
181 } else {
182 return newSharedLeakAwareByteBuf(super.order(endianness));
183 }
184 }
185
186 private ByteBuf unwrappedDerived(ByteBuf derived) {
187
188
189 ByteBuf unwrappedDerived = unwrapSwapped(derived);
190
191 if (unwrappedDerived instanceof AbstractPooledDerivedByteBuf) {
192
193 ((AbstractPooledDerivedByteBuf) unwrappedDerived).parent(this);
194
195
196 return newLeakAwareByteBuf(derived, AbstractByteBuf.leakDetector.trackForcibly(derived));
197 }
198 return newSharedLeakAwareByteBuf(derived);
199 }
200
201 @SuppressWarnings("deprecation")
202 private static ByteBuf unwrapSwapped(ByteBuf buf) {
203 if (buf instanceof SwappedByteBuf) {
204 do {
205 buf = buf.unwrap();
206 } while (buf instanceof SwappedByteBuf);
207
208 return buf;
209 }
210 return buf;
211 }
212
213 private SimpleLeakAwareByteBuf newSharedLeakAwareByteBuf(
214 ByteBuf wrapped) {
215 return newLeakAwareByteBuf(wrapped, trackedByteBuf, leak);
216 }
217
218 private SimpleLeakAwareByteBuf newLeakAwareByteBuf(
219 ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leakTracker) {
220 return newLeakAwareByteBuf(wrapped, wrapped, leakTracker);
221 }
222
223 protected SimpleLeakAwareByteBuf newLeakAwareByteBuf(
224 ByteBuf buf, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leakTracker) {
225 return new SimpleLeakAwareByteBuf(buf, trackedByteBuf, leakTracker);
226 }
227 }