SaferAlloc is a small JNI binding that provides hardened native memory allocation for java. The underlying implementations are platform-specific and might change over time.
| Platform | Underlying Allocator | Notes |
|---|---|---|
| Linux x86_64 | mimalloc | mimalloc with MI_SECURE=ON |
| Linux aarch64 | mimalloc | mimalloc with MI_SECURE=ON |
| macOS x86_64 | mimalloc | mimalloc with MI_SECURE=ON |
| macOS aarch64 | mimalloc | mimalloc with MI_SECURE=ON |
| Windows x86_64 | mimalloc | mimalloc with MI_SECURE=ON |
| Windows aarch64 | mimalloc | mimalloc with MI_SECURE=ON |
| Android 11+ | passthrough | Modern Android has its own hardened allocator (Scudo), so we just pass through. |
| iOS 15+ | passthrough | iOS uses Apple libmalloc, which includes platform allocator hardening, so we just pass through. The native artifact is packaged as a static xcframework for libJGLIOS. |
org.ngengine.saferalloc.SaferAlloc exposes:
ByteBuffer malloc(int size)ByteBuffer calloc(int count, int size)ByteBuffer realloc(ByteBuffer buffer, int newSize)ByteBuffer mallocAligned(int size, int alignment)void free(ByteBuffer buffer)void free(long address)long address(ByteBuffer buffer)
Notes:
malloc/calloc/mallocAlignedreturnnullon allocation failure.realloc(buffer, newSize)throwsOutOfMemoryErrorif a non-null buffer cannot be resized, including when its replacement Java wrapper cannot be allocated. The old allocation remains valid on failure.realloc(buffer, 0)returnsnulland frees the old allocation.realloc(null, newSize)behaves likemalloc(newSize)for positive sizes;realloc(null, 0)returnsnull.- High-level
reallocallocates a separate native block and Java wrapper before copyingmin(buffer.capacity(), newSize)bytes and freeing the original. It ignores the original position and limit, and the returned buffer has position zero and limitnewSize. This guarantees exception safety at the cost of copying and temporarily holding both allocations, even when shrinking or keeping the same size. Native reallocation function pointers retain their existing in-place-capable behavior. - invalid sizes throw
IllegalArgumentException. mallocAligned(size, alignment)requiresalignmentto be a power of two and a multiple of pointer size.calloc(count, size)rejects capacities larger thanInteger.MAX_VALUE.
- This API manages native memory manually. Always call
free(buffer). - Pass only live, owning buffers returned by SaferAlloc to
reallocorfree, not slices, duplicates, or buffers allocated elsewhere. These operations do not track ownership. - After successful
realloc, treat the old buffer and any views as invalid and use the returned one only. Ifreallocthrows, keep using the old buffer (it is still allocated). free(null)is a no-op.