CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-bytedeco--cpython

JavaCPP bindings for CPython 3.13.5 enabling Java applications to embed Python interpreters and interact with Python objects through the Python C API

Pending
Overview
Eval results
Files

memory-management.mddocs/

Memory Management

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.

Capabilities

Raw Memory Allocation

Low-level memory allocation functions similar to C's malloc/free family, without GIL requirements.

/**
 * Allocate raw memory block
 * @param size - Size in bytes to allocate
 * @return Pointer to allocated memory, or NULL on failure
 */
public static native Pointer PyMem_RawMalloc(long size);

/**
 * Allocate and zero-initialize raw memory block
 * @param nelem - Number of elements
 * @param elsize - Size of each element in bytes
 * @return Pointer to allocated memory, or NULL on failure
 */
public static native Pointer PyMem_RawCalloc(long nelem, long elsize);

/**
 * Resize raw memory block
 * @param ptr - Pointer to existing memory block (or NULL)
 * @param new_size - New size in bytes
 * @return Pointer to resized memory, or NULL on failure
 */
public static native Pointer PyMem_RawRealloc(Pointer ptr, long new_size);

/**
 * Free raw memory block
 * @param ptr - Pointer to memory to free (NULL safe)
 */
public static native void PyMem_RawFree(Pointer ptr);

Usage Example:

import static org.bytedeco.cpython.global.python.*;

// Allocate raw memory (no GIL required)
Pointer buffer = PyMem_RawMalloc(1024);
if (buffer != null) {
    // Use buffer
    
    // Resize if needed
    buffer = PyMem_RawRealloc(buffer, 2048);
    
    // Always free when done
    PyMem_RawFree(buffer);
}

Python Memory Allocation

Python-aware memory allocation that integrates with the GIL and Python's memory management system.

/**
 * Allocate memory using Python's allocator
 * @param size - Size in bytes to allocate
 * @return Pointer to allocated memory, or NULL on failure
 */
public static native Pointer PyMem_Malloc(long size);

/**
 * Allocate and zero-initialize memory using Python's allocator
 * @param nelem - Number of elements
 * @param elsize - Size of each element in bytes
 * @return Pointer to allocated memory, or NULL on failure
 */
public static native Pointer PyMem_Calloc(long nelem, long elsize);

/**
 * Resize memory block using Python's allocator
 * @param ptr - Pointer to existing memory block (or NULL)
 * @param new_size - New size in bytes
 * @return Pointer to resized memory, or NULL on failure
 */
public static native Pointer PyMem_Realloc(Pointer ptr, long new_size);

/**
 * Free memory allocated by Python's allocator
 * @param ptr - Pointer to memory to free (NULL safe)
 */
public static native void PyMem_Free(Pointer ptr);

Usage Example:

// Allocate memory (requires GIL)
int gilState = PyGILState_Ensure();
try {
    Pointer pythonMem = PyMem_Malloc(512);
    if (pythonMem != null) {
        // Use memory for Python-related operations
        
        // Free when done
        PyMem_Free(pythonMem);
    }
} finally {
    PyGILState_Release(gilState);
}

Memory Allocator Management

Functions for managing and configuring Python's memory allocators.

/**
 * Get current memory allocator for domain
 * @param domain - Memory domain (PYMEM_DOMAIN_RAW, PYMEM_DOMAIN_MEM, etc.)
 * @param allocator - Structure to receive allocator info
 */
public static native void PyMem_GetAllocator(int domain, PyMemAllocatorEx allocator);

/**
 * Set memory allocator for domain
 * @param domain - Memory domain to configure
 * @param allocator - New allocator configuration
 */
public static native void PyMem_SetAllocator(int domain, PyMemAllocatorEx allocator);

/**
 * Setup debug hooks for memory allocation
 */
public static native void PyMem_SetupDebugHooks();

Object Memory Management

Specialized memory allocation for Python objects and types.

/**
 * Generic allocation for Python type instances
 * @param type - Type to allocate instance of
 * @param nitems - Number of items (for variable-length objects)
 * @return New object instance, or NULL on failure
 */
public static native PyObject PyType_GenericAlloc(PyTypeObject type, long nitems);

Usage Example:

// Allocate instance of a specific type
PyTypeObject listType = PyList_Type(); // Assuming this function exists
PyObject newList = PyType_GenericAlloc(listType, 0);

if (newList != null) {
    // Initialize the object as needed
    // Note: Generic allocation may require additional initialization
}

Memory Constants and Utilities

Important constants and utility values for memory operations.

/**
 * Immortal reference count value (objects that are never deallocated)
 */
public static final long _Py_IMMORTAL_REFCNT = _Py_IMMORTAL_REFCNT();

/**
 * Invalid size marker
 */
public static final long Py_INVALID_SIZE = (long)-1;

Memory Allocator Structure

/**
 * Memory allocator configuration structure
 */
class PyMemAllocatorEx extends Pointer {
    // Contains function pointers for:
    // - malloc function
    // - calloc function  
    // - realloc function
    // - free function
    // - context pointer for allocator data
}

Memory Domains

Python uses different memory domains for different purposes:

// Memory domain constants (typical values - check actual bindings)
public static final int PYMEM_DOMAIN_RAW = 0;    // Raw memory (no GIL)
public static final int PYMEM_DOMAIN_MEM = 1;    // Python memory (with GIL)
public static final int PYMEM_DOMAIN_OBJ = 2;    // Object memory

Advanced Memory Management Patterns

Custom Allocator Setup

import static org.bytedeco.cpython.global.python.*;

// Get current allocator
PyMemAllocatorEx currentAllocator = new PyMemAllocatorEx();
PyMem_GetAllocator(PYMEM_DOMAIN_MEM, currentAllocator);

// Save for restoration later
PyMemAllocatorEx savedAllocator = new PyMemAllocatorEx();
PyMem_GetAllocator(PYMEM_DOMAIN_MEM, savedAllocator);

// Set debug allocator
PyMem_SetupDebugHooks();

// ... use Python with debug memory tracking ...

// Restore original allocator
PyMem_SetAllocator(PYMEM_DOMAIN_MEM, savedAllocator);

Memory Usage Monitoring

// Enable debug hooks to track memory usage
PyMem_SetupDebugHooks();

// Allocate some Python objects
PyObject list = PyList_New(1000);
for (int i = 0; i < 1000; i++) {
    PyObject item = PyLong_FromLong(i);
    PyList_SetItem(list, i, item);
}

// Debug hooks will track allocations and detect leaks

Large Memory Allocation

// For large allocations, consider using raw allocator
// to avoid GIL overhead
long largeSize = 1024 * 1024 * 100; // 100MB

Pointer largeBuffer = PyMem_RawMalloc(largeSize);
if (largeBuffer != null) {
    try {
        // Use buffer for bulk operations
        // Process data without holding GIL unnecessarily
        
    } finally {
        PyMem_RawFree(largeBuffer);
    }
}

Memory-Efficient Object Creation

// Pre-allocate containers to avoid repeated reallocations
PyObject list = PyList_New(1000); // Pre-size for expected items

// Use PyList_SET_ITEM for pre-allocated slots (faster)
for (int i = 0; i < 1000; i++) {
    PyObject item = PyLong_FromLong(i);
    PyList_SET_ITEM(list, i, item); // No bounds checking
}

Memory Management Best Practices

Choose the Right Allocator

// Use raw allocator for:
// - Large temporary buffers
// - Non-Python data structures  
// - Operations without GIL
Pointer tempBuffer = PyMem_RawMalloc(bufferSize);

// Use Python allocator for:
// - Python object creation
// - Operations requiring GIL
// - Memory that may be tracked by Python
Pointer pythonBuffer = PyMem_Malloc(bufferSize);

Memory Leak Prevention

Pointer memory = null;
try {
    memory = PyMem_Malloc(1024);
    if (memory == null) {
        // Handle allocation failure
        return;
    }
    
    // Use memory
    
} finally {
    // Always free in finally block
    if (memory != null) {
        PyMem_Free(memory);
    }
}

Exception Safety

PyObject obj1 = null;
PyObject obj2 = null;

try {
    obj1 = PyList_New(10);
    if (obj1 == null || PyErr_Occurred() != null) {
        throw new RuntimeException("Failed to create list");
    }
    
    obj2 = PyDict_New();
    if (obj2 == null || PyErr_Occurred() != null) {
        throw new RuntimeException("Failed to create dict");
    }
    
    // Use objects
    
} catch (Exception e) {
    // Clean up on exception
    // Note: In real usage, objects are typically managed
    // by Python's reference counting system
    throw e;
}

Memory Debugging

// Enable memory debugging
PyMem_SetupDebugHooks();

// Create objects that might leak
PyObject potentialLeak = createComplexStructure();

// Force garbage collection to detect issues
System.gc(); // Java GC
// Python GC would be triggered through PyRun_SimpleString("import gc; gc.collect()")

// Debug hooks will report any issues

Integration with Java Memory Management

JavaCPP Integration

The JavaCPP framework automatically manages the lifecycle of native objects:

// JavaCPP handles native memory cleanup
PyObject obj = new PyObject() {
    { 
        // Object initialization
    }
    
    @Override
    public void deallocate() {
        // Custom cleanup if needed
        super.deallocate();
    }
};

// Object will be cleaned up when Java object is GC'd

Cross-Language Memory Considerations

// When passing data between Java and Python:

// 1. Java -> Python: Copy data or ensure Java object lifetime
byte[] javaData = getDataFromJava();
Pointer pythonBuffer = PyMem_Malloc(javaData.length);
pythonBuffer.put(javaData); // Copy to Python-managed memory

// 2. Python -> Java: Copy data before Python object is freed
PyObject pythonString = getPythonString();
String javaString = PyUnicode_AsUTF8(pythonString); // Immediate copy

Important Notes

GIL Requirements

  • Raw allocator functions: No GIL required, thread-safe
  • Python allocator functions: Require GIL to be held
  • Object allocation functions: Always require GIL

Error Handling

Memory allocation functions return NULL on failure. Always check return values and handle allocation failures gracefully.

Platform Considerations

Memory allocation behavior may vary between platforms. The debug hooks and allocator management functions help ensure consistent behavior across platforms.

Performance Considerations

  • Use raw allocators for large temporary buffers
  • Pre-allocate containers when final size is known
  • Avoid frequent small allocations - batch operations when possible
  • Consider memory alignment for performance-critical operations

Install with Tessl CLI

npx tessl i tessl/maven-org-bytedeco--cpython

docs

exceptions.md

index.md

initialization.md

memory-management.md

modules.md

objects.md

utilities.md

tile.json