0
# Buffer Management
1
2
Jetty IO provides a sophisticated buffer management system built around reference counting and pooling for efficient memory usage in high-throughput network applications.
3
4
## Capabilities
5
6
### ByteBufferPool Interface
7
8
The ByteBufferPool interface provides pooled ByteBuffer instances wrapped in RetainableByteBuffer for automatic memory management.
9
10
```java { .api }
11
/**
12
* Pool for RetainableByteBuffer instances with reference counting
13
*/
14
interface ByteBufferPool {
15
/**
16
* Acquire a buffer from the pool
17
* @param size minimum buffer size required
18
* @param direct whether to prefer direct buffers
19
* @return RetainableByteBuffer instance
20
*/
21
RetainableByteBuffer acquire(int size, boolean direct);
22
23
/** Clear all non-retained buffers from the pool */
24
void clear();
25
26
// Default implementations
27
ByteBufferPool NON_POOLING = new NonPooling();
28
ByteBufferPool SIZED_NON_POOLING = new Sized(new NonPooling(), 1024, true);
29
30
class Wrapper implements ByteBufferPool {
31
private final ByteBufferPool wrapped;
32
33
public Wrapper(ByteBufferPool wrapped);
34
public ByteBufferPool getWrapped();
35
public RetainableByteBuffer acquire(int size, boolean direct);
36
public void clear();
37
}
38
39
class Sized implements ByteBufferPool {
40
public Sized(ByteBufferPool pool, int size, boolean direct);
41
public RetainableByteBuffer acquire(int size, boolean direct);
42
}
43
44
class NonPooling implements ByteBufferPool {
45
public RetainableByteBuffer acquire(int size, boolean direct);
46
public void clear();
47
}
48
49
class Accumulator {
50
public Accumulator();
51
public int getLength();
52
public void append(ByteBuffer buffer);
53
public ByteBuffer[] toByteBuffers();
54
public void writeTo(WritableByteChannel channel) throws IOException;
55
}
56
}
57
```
58
59
**Usage Examples:**
60
61
```java
62
// Basic buffer acquisition and release
63
ByteBufferPool pool = new ArrayByteBufferPool();
64
RetainableByteBuffer buffer = pool.acquire(1024, false);
65
try {
66
ByteBuffer bb = buffer.getByteBuffer();
67
// Use buffer for I/O operations
68
bb.put("Hello World".getBytes());
69
} finally {
70
buffer.release(); // Always release when done
71
}
72
73
// Using wrapper for additional functionality
74
ByteBufferPool wrappedPool = new ByteBufferPool.Wrapper(pool) {
75
@Override
76
public RetainableByteBuffer acquire(int size, boolean direct) {
77
System.out.println("Acquiring buffer of size: " + size);
78
return super.acquire(size, direct);
79
}
80
};
81
82
// Using sized pool for consistent buffer sizes
83
ByteBufferPool sizedPool = new ByteBufferPool.Sized(pool, 4096, true);
84
RetainableByteBuffer fixedBuffer = sizedPool.acquire(100, false); // Returns 4096 byte buffer
85
```
86
87
### RetainableByteBuffer Interface
88
89
Reference-counted ByteBuffer wrapper that integrates with the pooling system.
90
91
```java { .api }
92
/**
93
* Reference-counted ByteBuffer with pool integration
94
*/
95
interface RetainableByteBuffer extends Retainable {
96
/** Get the wrapped ByteBuffer */
97
ByteBuffer getByteBuffer();
98
99
/** Check if this buffer is currently retained */
100
boolean isRetained();
101
102
/** Check if underlying buffer is direct */
103
boolean isDirect();
104
105
/** Get number of remaining bytes */
106
int remaining();
107
108
/** Check if buffer has remaining bytes */
109
boolean hasRemaining();
110
111
/** Get buffer capacity */
112
int capacity();
113
114
/** Clear the buffer (reset position/limit) */
115
void clear();
116
117
// Static factory methods
118
static RetainableByteBuffer wrap(ByteBuffer buffer);
119
static RetainableByteBuffer wrap(ByteBuffer buffer, Retainable retainable);
120
121
// Constants
122
RetainableByteBuffer EMPTY = new EmptyRetainableByteBuffer();
123
}
124
```
125
126
**Usage Examples:**
127
128
```java
129
// Creating retainable buffers
130
ByteBuffer rawBuffer = ByteBuffer.allocate(1024);
131
RetainableByteBuffer retainable = RetainableByteBuffer.wrap(rawBuffer);
132
133
// With custom retainable for cleanup
134
RetainableByteBuffer customRetainable = RetainableByteBuffer.wrap(rawBuffer, () -> {
135
// Custom cleanup logic
136
System.out.println("Buffer released");
137
});
138
139
// Sharing buffer reference
140
retainable.retain(); // Increment reference count
141
// Pass to another component...
142
// Both components must call release() when done
143
144
// Buffer operations
145
ByteBuffer bb = retainable.getByteBuffer();
146
bb.put("data".getBytes());
147
System.out.println("Remaining: " + retainable.remaining());
148
System.out.println("Is direct: " + retainable.isDirect());
149
```
150
151
### Retainable Interface
152
153
Core reference counting abstraction for automatic resource management.
154
155
```java { .api }
156
/**
157
* Reference counting abstraction for borrowed resources
158
*/
159
interface Retainable {
160
/** Check if reference counting is enabled */
161
boolean canRetain();
162
163
/** Increment reference count */
164
void retain();
165
166
/**
167
* Decrement reference count
168
* @return true when reference count reaches zero
169
*/
170
boolean release();
171
172
class Wrapper implements Retainable {
173
private final Retainable wrapped;
174
175
public Wrapper(Retainable wrapped);
176
public Retainable getWrapped();
177
public boolean canRetain();
178
public void retain();
179
public boolean release();
180
}
181
182
class ReferenceCounter implements Retainable {
183
public ReferenceCounter();
184
public boolean canRetain();
185
public void retain();
186
public boolean release();
187
}
188
}
189
```
190
191
**Usage Examples:**
192
193
```java
194
// Basic reference counting
195
Retainable resource = new Retainable.ReferenceCounter();
196
197
// Share resource (increment count)
198
resource.retain();
199
processInBackground(resource); // Will call release() when done
200
201
// Original holder releases
202
boolean shouldCleanup = resource.release(); // Returns false (count > 0)
203
204
// Background processing completes
205
boolean shouldCleanup2 = resource.release(); // Returns true (count = 0)
206
if (shouldCleanup2) {
207
// Perform cleanup
208
}
209
210
// Wrapper for adding behavior
211
Retainable wrappedResource = new Retainable.Wrapper(resource) {
212
@Override
213
public boolean release() {
214
boolean result = super.release();
215
if (result) {
216
System.out.println("Resource fully released");
217
}
218
return result;
219
}
220
};
221
```
222
223
### ArrayByteBufferPool Implementation
224
225
High-performance array-based buffer pool implementation.
226
227
```java { .api }
228
/**
229
* High-performance array-based byte buffer pool
230
*/
231
class ArrayByteBufferPool implements ByteBufferPool {
232
public ArrayByteBufferPool();
233
public ArrayByteBufferPool(int minSize, int factor, int maxSize);
234
public ArrayByteBufferPool(int minSize, int factor, int maxSize, int maxBucketSize);
235
public ArrayByteBufferPool(int minSize, int factor, int maxSize, int maxBucketSize, long maxHeapMemory, long maxDirectMemory);
236
237
public RetainableByteBuffer acquire(int size, boolean direct);
238
public void clear();
239
240
// Configuration methods
241
public int getMinSize();
242
public int getFactor();
243
public int getMaxSize();
244
public int getMaxBucketSize();
245
public long getMaxHeapMemory();
246
public long getMaxDirectMemory();
247
248
// Statistics
249
public long getHeapMemory();
250
public long getDirectMemory();
251
public String toString();
252
}
253
```
254
255
**Configuration Example:**
256
257
```java
258
// Default configuration
259
ArrayByteBufferPool defaultPool = new ArrayByteBufferPool();
260
261
// Custom configuration
262
ArrayByteBufferPool customPool = new ArrayByteBufferPool(
263
64, // minSize: smallest buffer size
264
2, // factor: size multiplication factor
265
65536, // maxSize: largest buffer size
266
64, // maxBucketSize: max buffers per size bucket
267
1024*1024, // maxHeapMemory: max heap memory for pool
268
2*1024*1024 // maxDirectMemory: max direct memory for pool
269
);
270
271
// Monitor pool usage
272
System.out.println("Heap memory used: " + customPool.getHeapMemory());
273
System.out.println("Direct memory used: " + customPool.getDirectMemory());
274
```
275
276
### Buffer Accumulation and Aggregation
277
278
#### ByteBufferAccumulator
279
280
Utility for accumulating multiple ByteBuffers into a sequence.
281
282
```java { .api }
283
/**
284
* Accumulator for ByteBuffer sequences
285
*/
286
class ByteBufferAccumulator implements Closeable {
287
public ByteBufferAccumulator(ByteBufferPool pool, boolean direct);
288
289
public int getLength();
290
public void append(byte[] bytes);
291
public void append(byte[] bytes, int offset, int length);
292
public void append(ByteBuffer buffer);
293
public ByteBuffer[] toByteBuffers();
294
public ByteBuffer toByteBuffer();
295
public void writeTo(WritableByteChannel channel) throws IOException;
296
public void close();
297
}
298
```
299
300
#### ByteBufferAggregator
301
302
Utility for aggregating ByteBuffers with size limits.
303
304
```java { .api }
305
/**
306
* Aggregates ByteBuffers with size limits
307
*/
308
class ByteBufferAggregator {
309
public ByteBufferAggregator(ByteBufferPool pool, boolean direct, int size, int maxSize);
310
311
public boolean aggregate(ByteBuffer buffer);
312
public ByteBuffer takeByteBuffer();
313
public void close();
314
315
public int getSize();
316
public int getMaxSize();
317
}
318
```
319
320
**Usage Examples:**
321
322
```java
323
// Accumulating multiple buffers
324
ByteBufferAccumulator accumulator = new ByteBufferAccumulator(pool, false);
325
try {
326
accumulator.append("Hello ".getBytes());
327
accumulator.append("World".getBytes());
328
329
// Get as single buffer
330
ByteBuffer combined = accumulator.toByteBuffer();
331
332
// Or get as array
333
ByteBuffer[] buffers = accumulator.toByteBuffers();
334
335
// Write to channel
336
FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE);
337
accumulator.writeTo(channel);
338
} finally {
339
accumulator.close();
340
}
341
342
// Aggregating with size limits
343
ByteBufferAggregator aggregator = new ByteBufferAggregator(pool, false, 1024, 8192);
344
try {
345
ByteBuffer chunk1 = ByteBuffer.wrap("data1".getBytes());
346
ByteBuffer chunk2 = ByteBuffer.wrap("data2".getBytes());
347
348
boolean aggregated1 = aggregator.aggregate(chunk1); // true
349
boolean aggregated2 = aggregator.aggregate(chunk2); // true if fits
350
351
// Take aggregated result
352
ByteBuffer result = aggregator.takeByteBuffer();
353
} finally {
354
aggregator.close();
355
}
356
```
357
358
### Stream Integration
359
360
#### ByteBufferInputStream and ByteBufferOutputStream
361
362
Stream adapters for ByteBuffer operations.
363
364
```java { .api }
365
/**
366
* InputStream backed by ByteBuffer
367
*/
368
class ByteBufferInputStream extends InputStream {
369
public ByteBufferInputStream(ByteBuffer buffer);
370
371
public int read();
372
public int read(byte[] b, int off, int len);
373
public int available();
374
public void close();
375
}
376
377
/**
378
* OutputStream that writes to ByteBuffer
379
*/
380
class ByteBufferOutputStream extends OutputStream {
381
public ByteBufferOutputStream(ByteBuffer buffer);
382
383
public void write(int b);
384
public void write(byte[] b, int off, int len);
385
public ByteBuffer getByteBuffer();
386
public void close();
387
}
388
```
389
390
**Usage Examples:**
391
392
```java
393
// Reading from ByteBuffer as InputStream
394
ByteBuffer buffer = ByteBuffer.wrap("Hello World".getBytes());
395
try (ByteBufferInputStream input = new ByteBufferInputStream(buffer)) {
396
int data;
397
while ((data = input.read()) != -1) {
398
System.out.print((char) data);
399
}
400
}
401
402
// Writing to ByteBuffer as OutputStream
403
ByteBuffer buffer = ByteBuffer.allocate(1024);
404
try (ByteBufferOutputStream output = new ByteBufferOutputStream(buffer)) {
405
output.write("Hello World".getBytes());
406
ByteBuffer result = output.getByteBuffer();
407
result.flip();
408
// Use result buffer
409
}
410
```