or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmemory-management.mdptr-package.mdstructures-types.mdwindows.md

memory-management.mddocs/

0

# JNA Memory Management

1

2

This document covers JNA's memory management system, including the Pointer and Memory classes, type-safe memory operations, and by-reference parameter passing.

3

4

## Core Imports

5

6

```java { .api }

7

import com.sun.jna.Pointer;

8

import com.sun.jna.Memory;

9

import com.sun.jna.ptr.*;

10

```

11

12

## Pointer Class - Base Memory Access

13

14

The `Pointer` class provides type-safe access to native memory locations:

15

16

```java { .api }

17

/**

18

* Represents a pointer to native memory with type-safe access methods

19

*/

20

public class Pointer {

21

/**

22

* Read byte value from memory

23

* @param offset Byte offset from pointer base

24

* @return Byte value at offset

25

*/

26

public byte getByte(long offset);

27

28

/**

29

* Write byte value to memory

30

* @param offset Byte offset from pointer base

31

* @param value Byte value to write

32

*/

33

public void setByte(long offset, byte value);

34

35

/**

36

* Read short value from memory (2 bytes)

37

* @param offset Byte offset from pointer base

38

* @return Short value at offset

39

*/

40

public short getShort(long offset);

41

42

/**

43

* Write short value to memory

44

* @param offset Byte offset from pointer base

45

* @param value Short value to write

46

*/

47

public void setShort(long offset, short value);

48

49

/**

50

* Read int value from memory (4 bytes)

51

* @param offset Byte offset from pointer base

52

* @return Int value at offset

53

*/

54

public int getInt(long offset);

55

56

/**

57

* Write int value to memory

58

* @param offset Byte offset from pointer base

59

* @param value Int value to write

60

*/

61

public void setInt(long offset, int value);

62

63

/**

64

* Read long value from memory (8 bytes)

65

* @param offset Byte offset from pointer base

66

* @return Long value at offset

67

*/

68

public long getLong(long offset);

69

70

/**

71

* Write long value to memory

72

* @param offset Byte offset from pointer base

73

* @param value Long value to write

74

*/

75

public void setLong(long offset, long value);

76

77

/**

78

* Read float value from memory (4 bytes)

79

* @param offset Byte offset from pointer base

80

* @return Float value at offset

81

*/

82

public float getFloat(long offset);

83

84

/**

85

* Write float value to memory

86

* @param offset Byte offset from pointer base

87

* @param value Float value to write

88

*/

89

public void setFloat(long offset, float value);

90

91

/**

92

* Read double value from memory (8 bytes)

93

* @param offset Byte offset from pointer base

94

* @return Double value at offset

95

*/

96

public double getDouble(long offset);

97

98

/**

99

* Write double value to memory

100

* @param offset Byte offset from pointer base

101

* @param value Double value to write

102

*/

103

public void setDouble(long offset, double value);

104

105

/**

106

* Read pointer value from memory

107

* @param offset Byte offset from pointer base

108

* @return Pointer value at offset (may be null)

109

*/

110

public Pointer getPointer(long offset);

111

112

/**

113

* Write pointer value to memory

114

* @param offset Byte offset from pointer base

115

* @param value Pointer value to write (may be null)

116

*/

117

public void setPointer(long offset, Pointer value);

118

119

/**

120

* Read null-terminated string from memory

121

* @param offset Byte offset from pointer base

122

* @param encoding Character encoding (e.g., "UTF-8", "UTF-16")

123

* @return String read from memory

124

*/

125

public String getString(long offset, String encoding);

126

127

/**

128

* Write null-terminated string to memory

129

* @param offset Byte offset from pointer base

130

* @param value String to write

131

* @param encoding Character encoding

132

*/

133

public void setString(long offset, String value, String encoding);

134

135

/**

136

* Create shared view of memory region

137

* @param offset Byte offset from pointer base

138

* @param size Size of shared region in bytes

139

* @return New pointer sharing memory region

140

*/

141

public Pointer share(long offset, long size);

142

143

/**

144

* Get NIO ByteBuffer view of memory

145

* @param offset Byte offset from pointer base

146

* @param length Size of buffer in bytes

147

* @return ByteBuffer backed by native memory

148

*/

149

public java.nio.ByteBuffer getByteBuffer(long offset, long length);

150

}

151

```

152

153

## Memory Class - Heap Allocation

154

155

The `Memory` class extends `Pointer` to provide malloc-based native memory allocation:

156

157

```java { .api }

158

/**

159

* Pointer to memory obtained from native heap with bounds checking

160

*/

161

public class Memory extends Pointer {

162

/**

163

* Allocate native memory block

164

* @param size Number of bytes to allocate

165

* @throws OutOfMemoryError if allocation fails

166

*/

167

public Memory(long size);

168

169

/**

170

* Get allocated memory size

171

* @return Size in bytes

172

*/

173

public long size();

174

175

/**

176

* Clear memory to zero

177

*/

178

public void clear();

179

180

/**

181

* Check if memory is still allocated

182

* @return true if memory is valid

183

*/

184

public boolean valid();

185

186

/**

187

* Create aligned memory view

188

* @param byteBoundary Alignment boundary (must be power of 2)

189

* @return New pointer aligned to boundary

190

*/

191

public Pointer align(int byteBoundary);

192

193

/**

194

* Explicitly dispose of memory

195

* Note: Memory is automatically freed by finalizer

196

*/

197

public void dispose();

198

199

// Static utility methods

200

201

/**

202

* Force cleanup of GC'd ByteBuffers

203

*/

204

public static void purge();

205

206

/**

207

* Dispose all allocated Memory objects

208

*/

209

public static void disposeAll();

210

}

211

```

212

213

## Basic Memory Operations

214

215

```java { .api }

216

// Allocate 1KB buffer

217

Memory buffer = new Memory(1024);

218

219

// Write primitive values

220

buffer.setInt(0, 42);

221

buffer.setFloat(4, 3.14f);

222

buffer.setLong(8, 123456789L);

223

224

// Read values back

225

int intVal = buffer.getInt(0); // 42

226

float floatVal = buffer.getFloat(4); // 3.14f

227

long longVal = buffer.getLong(8); // 123456789L

228

229

// String operations with encoding

230

buffer.setString(16, "Hello World", "UTF-8");

231

String text = buffer.getString(16, "UTF-8"); // "Hello World"

232

233

// Pointer operations

234

Memory subBuffer = new Memory(256);

235

buffer.setPointer(100, subBuffer);

236

Pointer retrieved = buffer.getPointer(100);

237

```

238

239

## Memory Sharing and Views

240

241

```java { .api }

242

// Create large buffer

243

Memory mainBuffer = new Memory(1000);

244

245

// Create shared views of different regions

246

Pointer header = mainBuffer.share(0, 100); // First 100 bytes

247

Pointer data = mainBuffer.share(100, 800); // Next 800 bytes

248

Pointer footer = mainBuffer.share(900, 100); // Last 100 bytes

249

250

// Write to shared regions

251

header.setInt(0, 0xDEADBEEF); // Magic number in header

252

data.setString(0, "payload", "UTF-8");

253

footer.setInt(0, 0xCAFEBABE); // Magic number in footer

254

255

// Changes are visible in main buffer

256

int magic = mainBuffer.getInt(0); // 0xDEADBEEF

257

String payload = mainBuffer.getString(100, "UTF-8"); // "payload"

258

```

259

260

## ByteBuffer Integration

261

262

```java { .api }

263

// Get NIO ByteBuffer view

264

Memory buffer = new Memory(512);

265

java.nio.ByteBuffer nio = buffer.getByteBuffer(0, 512);

266

267

// Use NIO operations

268

nio.putInt(42);

269

nio.putFloat(3.14f);

270

nio.flip();

271

272

// Read back via buffer methods

273

int value = buffer.getInt(0); // 42

274

float fval = buffer.getFloat(4); // 3.14f

275

```

276

277

## By-Reference Parameter Passing

278

279

JNA provides specialized classes for passing primitive values by reference:

280

281

```java { .api }

282

import com.sun.jna.ptr.*;

283

284

/**

285

* Base class for all by-reference types

286

*/

287

public abstract class ByReference extends PointerType {

288

/**

289

* Create with specified data size

290

* @param dataSize Size in bytes of referenced data

291

*/

292

protected ByReference(int dataSize);

293

}

294

295

/**

296

* Reference to a byte value (char* in C)

297

*/

298

public class ByteByReference extends ByReference {

299

public ByteByReference();

300

public ByteByReference(byte value);

301

302

/**

303

* Set the referenced byte value

304

* @param value New byte value

305

*/

306

public void setValue(byte value);

307

308

/**

309

* Get the referenced byte value

310

* @return Current byte value

311

*/

312

public byte getValue();

313

}

314

315

/**

316

* Reference to a short value (short* in C)

317

*/

318

public class ShortByReference extends ByReference {

319

public ShortByReference();

320

public ShortByReference(short value);

321

322

public void setValue(short value);

323

public short getValue();

324

}

325

326

/**

327

* Reference to an int value (int* in C)

328

*/

329

public class IntByReference extends ByReference {

330

public IntByReference();

331

public IntByReference(int value);

332

333

public void setValue(int value);

334

public int getValue();

335

}

336

337

/**

338

* Reference to a long value (long* in C)

339

*/

340

public class LongByReference extends ByReference {

341

public LongByReference();

342

public LongByReference(long value);

343

344

public void setValue(long value);

345

public long getValue();

346

}

347

348

/**

349

* Reference to a float value (float* in C)

350

*/

351

public class FloatByReference extends ByReference {

352

public FloatByReference();

353

public FloatByReference(float value);

354

355

public void setValue(float value);

356

public float getValue();

357

}

358

359

/**

360

* Reference to a double value (double* in C)

361

*/

362

public class DoubleByReference extends ByReference {

363

public DoubleByReference();

364

public DoubleByReference(double value);

365

366

public void setValue(double value);

367

public double getValue();

368

}

369

370

/**

371

* Reference to a NativeLong value (long* on platform)

372

*/

373

public class NativeLongByReference extends ByReference {

374

public NativeLongByReference();

375

public NativeLongByReference(NativeLong value);

376

377

public void setValue(NativeLong value);

378

public NativeLong getValue();

379

}

380

381

/**

382

* Reference to a Pointer value (void** in C)

383

*/

384

public class PointerByReference extends ByReference {

385

public PointerByReference();

386

public PointerByReference(Pointer value);

387

388

public void setValue(Pointer value);

389

public Pointer getValue();

390

}

391

```

392

393

## By-Reference Usage Examples

394

395

```java { .api }

396

// Define native function that modifies parameters

397

public interface MyLibrary extends Library {

398

MyLibrary INSTANCE = Native.loadLibrary("mylib", MyLibrary.class);

399

400

/**

401

* Function that increments an integer value

402

* void increment(int* value);

403

*/

404

void increment(IntByReference value);

405

406

/**

407

* Function that swaps two float values

408

* void swap_floats(float* a, float* b);

409

*/

410

void swap_floats(FloatByReference a, FloatByReference b);

411

412

/**

413

* Function that allocates memory and returns pointer

414

* int create_buffer(void** buffer, int size);

415

*/

416

int create_buffer(PointerByReference buffer, int size);

417

}

418

419

// Usage examples

420

IntByReference counter = new IntByReference(10);

421

MyLibrary.INSTANCE.increment(counter);

422

int newValue = counter.getValue(); // 11

423

424

FloatByReference a = new FloatByReference(1.0f);

425

FloatByReference b = new FloatByReference(2.0f);

426

MyLibrary.INSTANCE.swap_floats(a, b);

427

// Now a.getValue() == 2.0f and b.getValue() == 1.0f

428

429

PointerByReference bufferRef = new PointerByReference();

430

int result = MyLibrary.INSTANCE.create_buffer(bufferRef, 1024);

431

if (result == 0) {

432

Pointer buffer = bufferRef.getValue();

433

// Use the allocated buffer...

434

}

435

```

436

437

## Native String Handling

438

439

```java { .api }

440

/**

441

* Wide character string for Unicode support

442

*/

443

public final class WString implements CharSequence, Comparable<Object> {

444

/**

445

* Create wide string from regular string

446

* @param s String to convert

447

*/

448

public WString(String s);

449

450

/**

451

* Get string value

452

* @return String representation

453

*/

454

public String toString();

455

456

/**

457

* Get length in characters

458

* @return Number of characters

459

*/

460

public int length();

461

462

/**

463

* Get character at index

464

* @param index Character index

465

* @return Character at index

466

*/

467

public char charAt(int index);

468

469

/**

470

* Get subsequence

471

* @param start Start index (inclusive)

472

* @param end End index (exclusive)

473

* @return Character subsequence

474

*/

475

public CharSequence subSequence(int start, int end);

476

}

477

478

// String usage examples

479

Memory buffer = new Memory(256);

480

481

// ASCII strings

482

buffer.setString(0, "Hello", "ASCII");

483

String ascii = buffer.getString(0, "ASCII");

484

485

// UTF-8 strings

486

buffer.setString(50, "Hello 世界", "UTF-8");

487

String utf8 = buffer.getString(50, "UTF-8");

488

489

// Wide strings (platform-specific Unicode)

490

WString wide = new WString("Hello 世界");

491

// Pass to native function expecting wchar_t*

492

```

493

494

## String Array Support

495

496

```java { .api }

497

/**

498

* Array of strings in native memory

499

*/

500

public class StringArray extends Memory {

501

/**

502

* Create from String array using default encoding

503

* @param strings Array of strings

504

*/

505

public StringArray(String[] strings);

506

507

/**

508

* Create from String array with encoding choice

509

* @param strings Array of strings

510

* @param wide true for wide character encoding

511

*/

512

public StringArray(String[] strings, boolean wide);

513

514

/**

515

* Create from WString array

516

* @param strings Array of wide strings

517

*/

518

public StringArray(WString[] strings);

519

}

520

521

// Usage example

522

String[] args = {"program", "--verbose", "input.txt"};

523

StringArray argv = new StringArray(args);

524

525

// Pass to native function expecting char**

526

public interface System extends Library {

527

int exec(String program, StringArray argv);

528

}

529

```

530

531

## Memory Safety and Best Practices

532

533

```java { .api }

534

// 1. Always check buffer bounds

535

Memory buffer = new Memory(1024);

536

if (offset + dataSize <= buffer.size()) {

537

buffer.setInt(offset, value);

538

}

539

540

// 2. Use try-with-resources pattern for explicit cleanup

541

class ManagedMemory extends Memory implements AutoCloseable {

542

public ManagedMemory(long size) { super(size); }

543

544

@Override

545

public void close() {

546

dispose();

547

}

548

}

549

550

try (ManagedMemory buffer = new ManagedMemory(1024)) {

551

// Use buffer...

552

} // Automatically disposed

553

554

// 3. Validate pointer before use

555

public void safeRead(Pointer ptr, long offset) {

556

if (ptr != null && ptr != Pointer.NULL) {

557

int value = ptr.getInt(offset);

558

// Use value...

559

}

560

}

561

562

// 4. Handle encoding explicitly

563

String text = "Hello 世界";

564

buffer.setString(0, text, "UTF-8"); // Explicit encoding

565

String result = buffer.getString(0, "UTF-8");

566

567

// 5. Use sharing for structured access

568

Memory packet = new Memory(100);

569

Pointer header = packet.share(0, 20); // 20-byte header

570

Pointer payload = packet.share(20, 80); // 80-byte payload

571

```

572

573

## Advanced Memory Operations

574

575

```java { .api }

576

// Memory alignment for performance

577

Memory buffer = new Memory(1000);

578

Pointer aligned = buffer.align(16); // 16-byte aligned access

579

580

// Zero memory efficiently

581

buffer.clear(); // Zeros entire buffer

582

583

// Bulk copy operations

584

Memory src = new Memory(100);

585

Memory dst = new Memory(100);

586

// Fill source with data...

587

src.write(0, dst.getByteArray(0, 100), 0, 100);

588

589

// Get raw bytes for processing

590

byte[] rawData = buffer.getByteArray(0, (int)buffer.size());

591

// Process rawData...

592

buffer.write(0, rawData, 0, rawData.length);

593

```

594

595

## Error Handling

596

597

```java { .api }

598

try {

599

Memory buffer = new Memory(1024 * 1024 * 1024); // 1GB

600

// Use buffer...

601

} catch (OutOfMemoryError e) {

602

System.err.println("Failed to allocate native memory: " + e.getMessage());

603

}

604

605

// Check memory validity

606

Memory buffer = new Memory(1024);

607

if (buffer.valid()) {

608

buffer.setInt(0, 42);

609

} else {

610

throw new IllegalStateException("Buffer has been disposed");

611

}

612

```

613

614

This comprehensive memory management system provides safe, efficient access to native memory while maintaining Java's type safety and automatic memory management principles.