JavaCPP bindings for CPython 3.13.5 enabling Java applications to embed Python interpreters and interact with Python objects through the Python C API
—
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.
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-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);
}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();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
}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 configuration structure
*/
class PyMemAllocatorEx extends Pointer {
// Contains function pointers for:
// - malloc function
// - calloc function
// - realloc function
// - free function
// - context pointer for allocator data
}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 memoryimport 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);// 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// 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);
}
}// 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
}// 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);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);
}
}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;
}// 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 issuesThe 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// 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 copyMemory allocation functions return NULL on failure. Always check return values and handle allocation failures gracefully.
Memory allocation behavior may vary between platforms. The debug hooks and allocator management functions help ensure consistent behavior across platforms.
Install with Tessl CLI
npx tessl i tessl/maven-org-bytedeco--cpython