0
# Memory Management
1
2
Direct access to Python's memory allocation system and garbage collection functionality. This includes raw memory operations, Python-aware memory allocation, object-specific allocation, and memory allocator management.
3
4
## Capabilities
5
6
### Raw Memory Allocation
7
8
Low-level memory allocation functions similar to C's malloc/free family, without GIL requirements.
9
10
```java { .api }
11
/**
12
* Allocate raw memory block
13
* @param size - Size in bytes to allocate
14
* @return Pointer to allocated memory, or NULL on failure
15
*/
16
public static native Pointer PyMem_RawMalloc(long size);
17
18
/**
19
* Allocate and zero-initialize raw memory block
20
* @param nelem - Number of elements
21
* @param elsize - Size of each element in bytes
22
* @return Pointer to allocated memory, or NULL on failure
23
*/
24
public static native Pointer PyMem_RawCalloc(long nelem, long elsize);
25
26
/**
27
* Resize raw memory block
28
* @param ptr - Pointer to existing memory block (or NULL)
29
* @param new_size - New size in bytes
30
* @return Pointer to resized memory, or NULL on failure
31
*/
32
public static native Pointer PyMem_RawRealloc(Pointer ptr, long new_size);
33
34
/**
35
* Free raw memory block
36
* @param ptr - Pointer to memory to free (NULL safe)
37
*/
38
public static native void PyMem_RawFree(Pointer ptr);
39
```
40
41
**Usage Example:**
42
43
```java
44
import static org.bytedeco.cpython.global.python.*;
45
46
// Allocate raw memory (no GIL required)
47
Pointer buffer = PyMem_RawMalloc(1024);
48
if (buffer != null) {
49
// Use buffer
50
51
// Resize if needed
52
buffer = PyMem_RawRealloc(buffer, 2048);
53
54
// Always free when done
55
PyMem_RawFree(buffer);
56
}
57
```
58
59
### Python Memory Allocation
60
61
Python-aware memory allocation that integrates with the GIL and Python's memory management system.
62
63
```java { .api }
64
/**
65
* Allocate memory using Python's allocator
66
* @param size - Size in bytes to allocate
67
* @return Pointer to allocated memory, or NULL on failure
68
*/
69
public static native Pointer PyMem_Malloc(long size);
70
71
/**
72
* Allocate and zero-initialize memory using Python's allocator
73
* @param nelem - Number of elements
74
* @param elsize - Size of each element in bytes
75
* @return Pointer to allocated memory, or NULL on failure
76
*/
77
public static native Pointer PyMem_Calloc(long nelem, long elsize);
78
79
/**
80
* Resize memory block using Python's allocator
81
* @param ptr - Pointer to existing memory block (or NULL)
82
* @param new_size - New size in bytes
83
* @return Pointer to resized memory, or NULL on failure
84
*/
85
public static native Pointer PyMem_Realloc(Pointer ptr, long new_size);
86
87
/**
88
* Free memory allocated by Python's allocator
89
* @param ptr - Pointer to memory to free (NULL safe)
90
*/
91
public static native void PyMem_Free(Pointer ptr);
92
```
93
94
**Usage Example:**
95
96
```java
97
// Allocate memory (requires GIL)
98
int gilState = PyGILState_Ensure();
99
try {
100
Pointer pythonMem = PyMem_Malloc(512);
101
if (pythonMem != null) {
102
// Use memory for Python-related operations
103
104
// Free when done
105
PyMem_Free(pythonMem);
106
}
107
} finally {
108
PyGILState_Release(gilState);
109
}
110
```
111
112
### Memory Allocator Management
113
114
Functions for managing and configuring Python's memory allocators.
115
116
```java { .api }
117
/**
118
* Get current memory allocator for domain
119
* @param domain - Memory domain (PYMEM_DOMAIN_RAW, PYMEM_DOMAIN_MEM, etc.)
120
* @param allocator - Structure to receive allocator info
121
*/
122
public static native void PyMem_GetAllocator(int domain, PyMemAllocatorEx allocator);
123
124
/**
125
* Set memory allocator for domain
126
* @param domain - Memory domain to configure
127
* @param allocator - New allocator configuration
128
*/
129
public static native void PyMem_SetAllocator(int domain, PyMemAllocatorEx allocator);
130
131
/**
132
* Setup debug hooks for memory allocation
133
*/
134
public static native void PyMem_SetupDebugHooks();
135
```
136
137
### Object Memory Management
138
139
Specialized memory allocation for Python objects and types.
140
141
```java { .api }
142
/**
143
* Generic allocation for Python type instances
144
* @param type - Type to allocate instance of
145
* @param nitems - Number of items (for variable-length objects)
146
* @return New object instance, or NULL on failure
147
*/
148
public static native PyObject PyType_GenericAlloc(PyTypeObject type, long nitems);
149
```
150
151
**Usage Example:**
152
153
```java
154
// Allocate instance of a specific type
155
PyTypeObject listType = PyList_Type(); // Assuming this function exists
156
PyObject newList = PyType_GenericAlloc(listType, 0);
157
158
if (newList != null) {
159
// Initialize the object as needed
160
// Note: Generic allocation may require additional initialization
161
}
162
```
163
164
### Memory Constants and Utilities
165
166
Important constants and utility values for memory operations.
167
168
```java { .api }
169
/**
170
* Immortal reference count value (objects that are never deallocated)
171
*/
172
public static final long _Py_IMMORTAL_REFCNT = _Py_IMMORTAL_REFCNT();
173
174
/**
175
* Invalid size marker
176
*/
177
public static final long Py_INVALID_SIZE = (long)-1;
178
```
179
180
### Memory Allocator Structure
181
182
```java { .api }
183
/**
184
* Memory allocator configuration structure
185
*/
186
class PyMemAllocatorEx extends Pointer {
187
// Contains function pointers for:
188
// - malloc function
189
// - calloc function
190
// - realloc function
191
// - free function
192
// - context pointer for allocator data
193
}
194
```
195
196
## Memory Domains
197
198
Python uses different memory domains for different purposes:
199
200
```java
201
// Memory domain constants (typical values - check actual bindings)
202
public static final int PYMEM_DOMAIN_RAW = 0; // Raw memory (no GIL)
203
public static final int PYMEM_DOMAIN_MEM = 1; // Python memory (with GIL)
204
public static final int PYMEM_DOMAIN_OBJ = 2; // Object memory
205
```
206
207
## Advanced Memory Management Patterns
208
209
### Custom Allocator Setup
210
211
```java
212
import static org.bytedeco.cpython.global.python.*;
213
214
// Get current allocator
215
PyMemAllocatorEx currentAllocator = new PyMemAllocatorEx();
216
PyMem_GetAllocator(PYMEM_DOMAIN_MEM, currentAllocator);
217
218
// Save for restoration later
219
PyMemAllocatorEx savedAllocator = new PyMemAllocatorEx();
220
PyMem_GetAllocator(PYMEM_DOMAIN_MEM, savedAllocator);
221
222
// Set debug allocator
223
PyMem_SetupDebugHooks();
224
225
// ... use Python with debug memory tracking ...
226
227
// Restore original allocator
228
PyMem_SetAllocator(PYMEM_DOMAIN_MEM, savedAllocator);
229
```
230
231
### Memory Usage Monitoring
232
233
```java
234
// Enable debug hooks to track memory usage
235
PyMem_SetupDebugHooks();
236
237
// Allocate some Python objects
238
PyObject list = PyList_New(1000);
239
for (int i = 0; i < 1000; i++) {
240
PyObject item = PyLong_FromLong(i);
241
PyList_SetItem(list, i, item);
242
}
243
244
// Debug hooks will track allocations and detect leaks
245
```
246
247
### Large Memory Allocation
248
249
```java
250
// For large allocations, consider using raw allocator
251
// to avoid GIL overhead
252
long largeSize = 1024 * 1024 * 100; // 100MB
253
254
Pointer largeBuffer = PyMem_RawMalloc(largeSize);
255
if (largeBuffer != null) {
256
try {
257
// Use buffer for bulk operations
258
// Process data without holding GIL unnecessarily
259
260
} finally {
261
PyMem_RawFree(largeBuffer);
262
}
263
}
264
```
265
266
### Memory-Efficient Object Creation
267
268
```java
269
// Pre-allocate containers to avoid repeated reallocations
270
PyObject list = PyList_New(1000); // Pre-size for expected items
271
272
// Use PyList_SET_ITEM for pre-allocated slots (faster)
273
for (int i = 0; i < 1000; i++) {
274
PyObject item = PyLong_FromLong(i);
275
PyList_SET_ITEM(list, i, item); // No bounds checking
276
}
277
```
278
279
## Memory Management Best Practices
280
281
### Choose the Right Allocator
282
283
```java
284
// Use raw allocator for:
285
// - Large temporary buffers
286
// - Non-Python data structures
287
// - Operations without GIL
288
Pointer tempBuffer = PyMem_RawMalloc(bufferSize);
289
290
// Use Python allocator for:
291
// - Python object creation
292
// - Operations requiring GIL
293
// - Memory that may be tracked by Python
294
Pointer pythonBuffer = PyMem_Malloc(bufferSize);
295
```
296
297
### Memory Leak Prevention
298
299
```java
300
Pointer memory = null;
301
try {
302
memory = PyMem_Malloc(1024);
303
if (memory == null) {
304
// Handle allocation failure
305
return;
306
}
307
308
// Use memory
309
310
} finally {
311
// Always free in finally block
312
if (memory != null) {
313
PyMem_Free(memory);
314
}
315
}
316
```
317
318
### Exception Safety
319
320
```java
321
PyObject obj1 = null;
322
PyObject obj2 = null;
323
324
try {
325
obj1 = PyList_New(10);
326
if (obj1 == null || PyErr_Occurred() != null) {
327
throw new RuntimeException("Failed to create list");
328
}
329
330
obj2 = PyDict_New();
331
if (obj2 == null || PyErr_Occurred() != null) {
332
throw new RuntimeException("Failed to create dict");
333
}
334
335
// Use objects
336
337
} catch (Exception e) {
338
// Clean up on exception
339
// Note: In real usage, objects are typically managed
340
// by Python's reference counting system
341
throw e;
342
}
343
```
344
345
### Memory Debugging
346
347
```java
348
// Enable memory debugging
349
PyMem_SetupDebugHooks();
350
351
// Create objects that might leak
352
PyObject potentialLeak = createComplexStructure();
353
354
// Force garbage collection to detect issues
355
System.gc(); // Java GC
356
// Python GC would be triggered through PyRun_SimpleString("import gc; gc.collect()")
357
358
// Debug hooks will report any issues
359
```
360
361
## Integration with Java Memory Management
362
363
### JavaCPP Integration
364
365
The JavaCPP framework automatically manages the lifecycle of native objects:
366
367
```java
368
// JavaCPP handles native memory cleanup
369
PyObject obj = new PyObject() {
370
{
371
// Object initialization
372
}
373
374
@Override
375
public void deallocate() {
376
// Custom cleanup if needed
377
super.deallocate();
378
}
379
};
380
381
// Object will be cleaned up when Java object is GC'd
382
```
383
384
### Cross-Language Memory Considerations
385
386
```java
387
// When passing data between Java and Python:
388
389
// 1. Java -> Python: Copy data or ensure Java object lifetime
390
byte[] javaData = getDataFromJava();
391
Pointer pythonBuffer = PyMem_Malloc(javaData.length);
392
pythonBuffer.put(javaData); // Copy to Python-managed memory
393
394
// 2. Python -> Java: Copy data before Python object is freed
395
PyObject pythonString = getPythonString();
396
String javaString = PyUnicode_AsUTF8(pythonString); // Immediate copy
397
```
398
399
## Important Notes
400
401
### GIL Requirements
402
403
- **Raw allocator functions**: No GIL required, thread-safe
404
- **Python allocator functions**: Require GIL to be held
405
- **Object allocation functions**: Always require GIL
406
407
### Error Handling
408
409
Memory allocation functions return NULL on failure. Always check return values and handle allocation failures gracefully.
410
411
### Platform Considerations
412
413
Memory allocation behavior may vary between platforms. The debug hooks and allocator management functions help ensure consistent behavior across platforms.
414
415
### Performance Considerations
416
417
- Use raw allocators for large temporary buffers
418
- Pre-allocate containers when final size is known
419
- Avoid frequent small allocations - batch operations when possible
420
- Consider memory alignment for performance-critical operations