or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-operations.mdbuffer-management.mdfilter-chain.mdindex.mdprotocol-codecs.mdservice-abstractions.mdsession-management.mdtransport-layer.md

buffer-management.mddocs/

0

# Buffer Management

1

2

MINA Core provides the `IoBuffer` class as an enhanced replacement for Java NIO's `ByteBuffer`. IoBuffer offers automatic expansion, convenient data manipulation methods, and optimized memory management for network applications.

3

4

## IoBuffer Basics

5

6

### Core Interface

7

8

```java { .api }

9

public abstract class IoBuffer implements Comparable<IoBuffer> {

10

// Allocation methods

11

static IoBuffer allocate(int capacity);

12

static IoBuffer allocate(int capacity, boolean direct);

13

static IoBuffer wrap(byte[] array);

14

static IoBuffer wrap(ByteBuffer nioBuffer);

15

16

// Buffer properties

17

int capacity();

18

int position();

19

IoBuffer position(int newPosition);

20

int limit();

21

IoBuffer limit(int newLimit);

22

int remaining();

23

boolean hasRemaining();

24

25

// Auto-expansion

26

boolean isAutoExpand();

27

IoBuffer setAutoExpand(boolean autoExpand);

28

boolean isAutoShrink();

29

IoBuffer setAutoShrink(boolean autoShrink);

30

31

// Buffer manipulation

32

IoBuffer clear();

33

IoBuffer flip();

34

IoBuffer rewind();

35

IoBuffer mark();

36

IoBuffer reset();

37

IoBuffer compact();

38

39

// Data access

40

byte get();

41

IoBuffer put(byte b);

42

byte get(int index);

43

IoBuffer put(int index, byte b);

44

45

// Bulk operations

46

IoBuffer get(byte[] dst);

47

IoBuffer put(byte[] src);

48

IoBuffer get(byte[] dst, int offset, int length);

49

IoBuffer put(byte[] src, int offset, int length);

50

51

// String operations

52

String getString(CharsetDecoder decoder) throws CharacterCodingException;

53

String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException;

54

IoBuffer putString(String value, CharsetEncoder encoder) throws CharacterCodingException;

55

String getHexDump();

56

String getHexDump(int lengthLimit);

57

}

58

```

59

60

## Buffer Allocation

61

62

### Basic Allocation

63

64

```java { .api }

65

// Allocate heap buffer

66

IoBuffer buffer = IoBuffer.allocate(1024);

67

68

// Allocate direct buffer (off-heap)

69

IoBuffer directBuffer = IoBuffer.allocate(1024, true);

70

71

// Set default buffer type

72

IoBuffer.setUseDirectBuffer(true); // Use direct buffers by default

73

IoBuffer defaultBuffer = IoBuffer.allocate(1024); // Now allocates direct buffer

74

75

// Check if buffer is direct

76

if (buffer.isDirect()) {

77

System.out.println("Using direct buffer");

78

} else {

79

System.out.println("Using heap buffer");

80

}

81

```

82

83

### Buffer Wrapping

84

85

```java { .api }

86

// Wrap byte array

87

byte[] data = "Hello, World!".getBytes("UTF-8");

88

IoBuffer wrapped = IoBuffer.wrap(data);

89

90

// Wrap NIO ByteBuffer

91

ByteBuffer nioBuffer = ByteBuffer.allocate(1024);

92

IoBuffer fromNio = IoBuffer.wrap(nioBuffer);

93

94

// Wrap with automatic expansion

95

IoBuffer autoExpanding = IoBuffer.wrap(data);

96

autoExpanding.setAutoExpand(true);

97

98

// Create buffer from existing buffer

99

IoBuffer original = IoBuffer.allocate(100);

100

IoBuffer duplicate = original.duplicate();

101

IoBuffer slice = original.slice();

102

IoBuffer readOnlyView = original.asReadOnlyBuffer();

103

```

104

105

## Auto-Expansion and Auto-Shrinking

106

107

### Auto-Expansion

108

109

```java { .api }

110

// Enable auto-expansion to handle variable-length data

111

IoBuffer buffer = IoBuffer.allocate(16);

112

buffer.setAutoExpand(true);

113

114

// Write data without worrying about capacity

115

String longMessage = "This is a very long message that exceeds the initial buffer capacity";

116

buffer.putString(longMessage, Charset.forName("UTF-8").newEncoder());

117

118

System.out.println("Buffer capacity grew to: " + buffer.capacity());

119

120

// Auto-expansion in action

121

public class AutoExpandExample {

122

123

public void writeVariableLengthData(IoSession session, List<String> messages) {

124

IoBuffer buffer = IoBuffer.allocate(64);

125

buffer.setAutoExpand(true);

126

127

// Write message count

128

buffer.putInt(messages.size());

129

130

// Write each message with length prefix

131

for (String message : messages) {

132

byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);

133

buffer.putInt(messageBytes.length); // Length prefix

134

buffer.put(messageBytes); // Message data

135

}

136

137

// Send the automatically sized buffer

138

buffer.flip();

139

session.write(buffer);

140

}

141

}

142

```

143

144

### Auto-Shrinking

145

146

```java { .api }

147

// Enable auto-shrinking to reclaim unused memory

148

IoBuffer buffer = IoBuffer.allocate(1024);

149

buffer.setAutoShrink(true);

150

151

// Fill buffer with data

152

byte[] data = new byte[500];

153

buffer.put(data);

154

buffer.flip();

155

156

// Process and clear data

157

processData(buffer);

158

buffer.clear();

159

160

// Buffer may shrink on next allocation if much smaller capacity is needed

161

// Auto-shrinking helps with memory efficiency in long-running applications

162

```

163

164

## Data Types and Operations

165

166

### Primitive Data Types

167

168

```java { .api }

169

// Write primitive types

170

IoBuffer buffer = IoBuffer.allocate(1024);

171

172

// Integers

173

buffer.putByte((byte) 42);

174

buffer.putShort((short) 1000);

175

buffer.putInt(123456);

176

buffer.putLong(123456789L);

177

178

// Floating point

179

buffer.putFloat(3.14f);

180

buffer.putDouble(2.71828);

181

182

// Character

183

buffer.putChar('A');

184

185

// Boolean (as byte)

186

buffer.put((byte) (true ? 1 : 0));

187

188

// Read primitive types

189

buffer.flip();

190

byte byteValue = buffer.get();

191

short shortValue = buffer.getShort();

192

int intValue = buffer.getInt();

193

long longValue = buffer.getLong();

194

float floatValue = buffer.getFloat();

195

double doubleValue = buffer.getDouble();

196

char charValue = buffer.getChar();

197

boolean boolValue = buffer.get() != 0;

198

```

199

200

### String Operations

201

202

```java { .api }

203

public class StringOperations {

204

205

public void stringExamples() throws CharacterCodingException {

206

IoBuffer buffer = IoBuffer.allocate(1024);

207

buffer.setAutoExpand(true);

208

209

// Write strings with different encodings

210

CharsetEncoder utf8Encoder = StandardCharsets.UTF_8.newEncoder();

211

CharsetEncoder utf16Encoder = StandardCharsets.UTF_16.newEncoder();

212

213

buffer.putString("Hello, World!", utf8Encoder);

214

buffer.putString("Привет, мир!", utf8Encoder); // Russian text

215

buffer.putString("こんにちは", utf16Encoder); // Japanese text

216

217

// Read strings back

218

buffer.flip();

219

CharsetDecoder utf8Decoder = StandardCharsets.UTF_8.newDecoder();

220

CharsetDecoder utf16Decoder = StandardCharsets.UTF_16.newDecoder();

221

222

String hello = buffer.getString(utf8Decoder);

223

String russian = buffer.getString(utf8Decoder);

224

String japanese = buffer.getString(utf16Decoder);

225

226

System.out.println("English: " + hello);

227

System.out.println("Russian: " + russian);

228

System.out.println("Japanese: " + japanese);

229

}

230

231

public void fixedLengthStrings() throws CharacterCodingException {

232

IoBuffer buffer = IoBuffer.allocate(100);

233

234

CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder();

235

CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();

236

237

// Write fixed-length string (padded/truncated to exact size)

238

String name = "John Doe";

239

buffer.putString(name, 20, encoder); // Always writes exactly 20 bytes

240

241

// Read fixed-length string

242

buffer.flip();

243

String readName = buffer.getString(20, decoder).trim();

244

System.out.println("Name: " + readName);

245

}

246

247

public void nullTerminatedStrings() throws CharacterCodingException {

248

IoBuffer buffer = IoBuffer.allocate(100);

249

250

CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder();

251

CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();

252

253

// Write null-terminated string

254

buffer.putString("Hello", encoder);

255

buffer.put((byte) 0); // Null terminator

256

257

// Read until null terminator

258

buffer.flip();

259

StringBuilder sb = new StringBuilder();

260

while (buffer.hasRemaining()) {

261

byte b = buffer.get();

262

if (b == 0) break;

263

sb.append((char) b);

264

}

265

266

System.out.println("Null-terminated string: " + sb.toString());

267

}

268

}

269

```

270

271

### Binary Data Operations

272

273

```java { .api }

274

public class BinaryOperations {

275

276

public void binaryDataExample() {

277

IoBuffer buffer = IoBuffer.allocate(1024);

278

279

// Write binary protocol header

280

buffer.put((byte) 0x01); // Version

281

buffer.put((byte) 0x02); // Message type

282

buffer.putShort((short) 1000); // Message length

283

buffer.putInt(System.currentTimeMillis()); // Timestamp

284

285

// Write payload

286

byte[] payload = createPayload();

287

buffer.put(payload);

288

289

// Update length field

290

int currentPos = buffer.position();

291

int messageLength = currentPos - 4; // Exclude header

292

buffer.putShort(2, (short) messageLength);

293

294

buffer.flip();

295

processMessage(buffer);

296

}

297

298

public void bitManipulation(IoBuffer buffer) {

299

// Pack multiple boolean flags into a single byte

300

boolean flag1 = true;

301

boolean flag2 = false;

302

boolean flag3 = true;

303

boolean flag4 = false;

304

305

byte flags = 0;

306

if (flag1) flags |= 0x01;

307

if (flag2) flags |= 0x02;

308

if (flag3) flags |= 0x04;

309

if (flag4) flags |= 0x08;

310

311

buffer.put(flags);

312

313

// Unpack flags

314

buffer.flip();

315

byte packedFlags = buffer.get();

316

boolean unpackedFlag1 = (packedFlags & 0x01) != 0;

317

boolean unpackedFlag2 = (packedFlags & 0x02) != 0;

318

boolean unpackedFlag3 = (packedFlags & 0x04) != 0;

319

boolean unpackedFlag4 = (packedFlags & 0x08) != 0;

320

}

321

}

322

```

323

324

## Buffer Utilities

325

326

### Hex Dump and Debugging

327

328

```java { .api }

329

public class BufferDebugging {

330

331

public void debugBuffer(IoBuffer buffer) {

332

System.out.println("=== Buffer Debug Information ===");

333

System.out.println("Capacity: " + buffer.capacity());

334

System.out.println("Position: " + buffer.position());

335

System.out.println("Limit: " + buffer.limit());

336

System.out.println("Remaining: " + buffer.remaining());

337

System.out.println("Auto-expand: " + buffer.isAutoExpand());

338

System.out.println("Auto-shrink: " + buffer.isAutoShrink());

339

System.out.println("Direct: " + buffer.isDirect());

340

System.out.println("Read-only: " + buffer.isReadOnly());

341

342

// Print hex dump

343

System.out.println("Hex dump:");

344

System.out.println(buffer.getHexDump());

345

346

// Print limited hex dump for large buffers

347

System.out.println("Hex dump (first 256 bytes):");

348

System.out.println(buffer.getHexDump(256));

349

}

350

351

public void compareBuffers(IoBuffer buffer1, IoBuffer buffer2) {

352

// Compare buffer contents

353

int comparison = buffer1.compareTo(buffer2);

354

355

if (comparison == 0) {

356

System.out.println("Buffers are identical");

357

} else if (comparison < 0) {

358

System.out.println("Buffer1 is lexicographically less than Buffer2");

359

} else {

360

System.out.println("Buffer1 is lexicographically greater than Buffer2");

361

}

362

363

// Check if buffers have same content

364

if (buffer1.equals(buffer2)) {

365

System.out.println("Buffers have same content");

366

}

367

}

368

}

369

```

370

371

### Buffer Pooling and Allocation

372

373

```java { .api }

374

// Custom buffer allocator for performance optimization

375

public class CustomBufferAllocator implements IoBufferAllocator {

376

private final boolean useDirectBuffer;

377

378

public CustomBufferAllocator(boolean useDirectBuffer) {

379

this.useDirectBuffer = useDirectBuffer;

380

}

381

382

@Override

383

public IoBuffer allocate(int capacity) {

384

return wrap(ByteBuffer.allocate(capacity));

385

}

386

387

@Override

388

public IoBuffer allocate(int capacity, boolean direct) {

389

ByteBuffer nioBuffer;

390

if (direct || useDirectBuffer) {

391

nioBuffer = ByteBuffer.allocateDirect(capacity);

392

} else {

393

nioBuffer = ByteBuffer.allocate(capacity);

394

}

395

return wrap(nioBuffer);

396

}

397

398

@Override

399

public IoBuffer wrap(ByteBuffer nioBuffer) {

400

return new CustomIoBuffer(nioBuffer);

401

}

402

403

@Override

404

public void dispose() {

405

// Cleanup resources if needed

406

}

407

}

408

409

// Set custom allocator

410

IoBuffer.setAllocator(new CustomBufferAllocator(true));

411

412

// Cached buffer allocator for better performance

413

CachedBufferAllocator cachedAllocator = new CachedBufferAllocator();

414

IoBuffer.setAllocator(cachedAllocator);

415

```

416

417

## Advanced Buffer Operations

418

419

### Buffer Slicing and Views

420

421

```java { .api }

422

public class BufferViews {

423

424

public void bufferSlicing() {

425

// Create original buffer with data

426

IoBuffer original = IoBuffer.allocate(100);

427

for (int i = 0; i < 50; i++) {

428

original.putInt(i);

429

}

430

431

// Create slice starting at position 20

432

original.position(20);

433

IoBuffer slice = original.slice();

434

435

// Slice shares data with original but has independent position/limit

436

slice.putInt(999); // Modifies original buffer at position 20

437

438

// Create duplicate with same content but independent position

439

original.rewind();

440

IoBuffer duplicate = original.duplicate();

441

442

// Create read-only view

443

IoBuffer readOnly = original.asReadOnlyBuffer();

444

445

// Read-only buffer throws exception on write attempts

446

try {

447

readOnly.putInt(123);

448

} catch (ReadOnlyBufferException e) {

449

System.out.println("Cannot write to read-only buffer");

450

}

451

}

452

453

public void bufferTypeViews() {

454

IoBuffer buffer = IoBuffer.allocate(100);

455

456

// Get typed views of buffer content

457

IntBuffer intView = buffer.asIntBuffer();

458

ShortBuffer shortView = buffer.asShortBuffer();

459

LongBuffer longView = buffer.asLongBuffer();

460

FloatBuffer floatView = buffer.asFloatBuffer();

461

DoubleBuffer doubleView = buffer.asDoubleBuffer();

462

CharBuffer charView = buffer.asCharBuffer();

463

464

// Use typed view for bulk operations

465

int[] intArray = {1, 2, 3, 4, 5};

466

intView.put(intArray);

467

468

// Read back using view

469

intView.rewind();

470

int[] readBack = new int[5];

471

intView.get(readBack);

472

}

473

}

474

```

475

476

### Stream Integration

477

478

```java { .api }

479

public class StreamIntegration {

480

481

public void bufferToStream() throws IOException {

482

IoBuffer buffer = IoBuffer.allocate(1024);

483

484

// Write data to buffer

485

buffer.putString("Hello, Stream!", StandardCharsets.UTF_8.newEncoder());

486

buffer.flip();

487

488

// Convert buffer to InputStream

489

InputStream inputStream = buffer.asInputStream();

490

491

// Read from stream

492

byte[] data = new byte[buffer.remaining()];

493

inputStream.read(data);

494

495

String result = new String(data, StandardCharsets.UTF_8);

496

System.out.println("Read from stream: " + result);

497

}

498

499

public void streamToBuffer() throws IOException {

500

// Create buffer as OutputStream

501

IoBuffer buffer = IoBuffer.allocate(1024);

502

buffer.setAutoExpand(true);

503

504

OutputStream outputStream = buffer.asOutputStream();

505

506

// Write to buffer via stream

507

String message = "Hello from OutputStream!";

508

outputStream.write(message.getBytes(StandardCharsets.UTF_8));

509

510

// Prepare buffer for reading

511

buffer.flip();

512

513

// Read the data

514

byte[] result = new byte[buffer.remaining()];

515

buffer.get(result);

516

517

System.out.println("Written via stream: " + new String(result, StandardCharsets.UTF_8));

518

}

519

}

520

```

521

522

### Memory-Mapped Buffers

523

524

```java { .api }

525

public class MemoryMappedBuffers {

526

527

public void createMappedBuffer(String filename) throws IOException {

528

try (RandomAccessFile file = new RandomAccessFile(filename, "rw")) {

529

FileChannel channel = file.getChannel();

530

531

// Create memory-mapped buffer

532

MappedByteBuffer mappedBuffer = channel.map(

533

FileChannel.MapMode.READ_WRITE, 0, 1024);

534

535

// Wrap in IoBuffer

536

IoBuffer buffer = IoBuffer.wrap(mappedBuffer);

537

538

// Write data directly to file via buffer

539

buffer.putString("Memory-mapped data", StandardCharsets.UTF_8.newEncoder());

540

541

// Force write to disk

542

if (mappedBuffer instanceof MappedByteBuffer) {

543

((MappedByteBuffer) buffer.buf()).force();

544

}

545

}

546

}

547

}

548

```

549

550

## Buffer Performance Optimization

551

552

### Efficient Buffer Usage

553

554

```java { .api }

555

public class BufferPerformance {

556

557

public void efficientBufferReuse() {

558

// Reuse buffers to reduce GC pressure

559

IoBuffer buffer = IoBuffer.allocate(1024);

560

561

for (int i = 0; i < 1000; i++) {

562

buffer.clear(); // Reset for reuse

563

564

// Write data

565

buffer.putInt(i);

566

buffer.putString("Message " + i, StandardCharsets.UTF_8.newEncoder());

567

568

// Process buffer

569

buffer.flip();

570

processBuffer(buffer);

571

572

// Buffer is reused in next iteration

573

}

574

}

575

576

public void bulkOperations() {

577

IoBuffer source = IoBuffer.allocate(10000);

578

IoBuffer destination = IoBuffer.allocate(10000);

579

580

// Fill source with data

581

byte[] data = new byte[5000];

582

Arrays.fill(data, (byte) 42);

583

source.put(data);

584

585

// Bulk copy is more efficient than individual byte operations

586

source.flip();

587

destination.put(source); // Bulk copy

588

589

// Instead of:

590

// while (source.hasRemaining()) {

591

// destination.put(source.get()); // Inefficient

592

// }

593

}

594

595

public void directBufferBenefits() {

596

// Direct buffers are more efficient for I/O operations

597

IoBuffer directBuffer = IoBuffer.allocate(1024, true);

598

IoBuffer heapBuffer = IoBuffer.allocate(1024, false);

599

600

// Direct buffer: no copying between Java heap and native memory

601

// Heap buffer: requires copying for I/O operations

602

603

// Use direct buffers for:

604

// - Large buffers

605

// - Long-lived buffers

606

// - High I/O throughput scenarios

607

608

// Use heap buffers for:

609

// - Small, short-lived buffers

610

// - Frequent allocation/deallocation

611

// - When avoiding off-heap memory limits

612

}

613

}

614

```

615

616

### Buffer Size Strategies

617

618

```java { .api }

619

public class BufferSizing {

620

621

public IoBuffer createOptimalBuffer(int estimatedSize) {

622

// Start with estimated size

623

int initialSize = Math.max(estimatedSize, 64); // Minimum 64 bytes

624

625

// Round up to next power of 2 for better memory alignment

626

int optimalSize = Integer.highestOneBit(initialSize - 1) << 1;

627

628

IoBuffer buffer = IoBuffer.allocate(optimalSize);

629

buffer.setAutoExpand(true); // Allow growth if needed

630

631

return buffer;

632

}

633

634

public void adaptiveBufferSizing(IoSession session) {

635

// Adapt buffer size based on session history

636

Long avgMessageSize = (Long) session.getAttribute("avgMessageSize");

637

638

if (avgMessageSize == null) {

639

avgMessageSize = 1024L; // Default size

640

}

641

642

// Create buffer with 50% headroom

643

int bufferSize = (int) (avgMessageSize * 1.5);

644

IoBuffer buffer = IoBuffer.allocate(bufferSize);

645

buffer.setAutoExpand(true);

646

647

// Update average after processing

648

updateAverageMessageSize(session, buffer.position());

649

}

650

651

private void updateAverageMessageSize(IoSession session, int currentSize) {

652

Long avgSize = (Long) session.getAttribute("avgMessageSize");

653

Long messageCount = (Long) session.getAttribute("messageCount");

654

655

if (avgSize == null) {

656

avgSize = (long) currentSize;

657

messageCount = 1L;

658

} else {

659

messageCount++;

660

avgSize = ((avgSize * (messageCount - 1)) + currentSize) / messageCount;

661

}

662

663

session.setAttribute("avgMessageSize", avgSize);

664

session.setAttribute("messageCount", messageCount);

665

}

666

}

667

```

668

669

IoBuffer provides a powerful and flexible foundation for handling binary data in MINA applications, with features that significantly simplify network programming compared to raw ByteBuffer usage.