Fix arena lifetime in record constructor #360

Merged
jwharm merged 1 commit from fix-record-arena into main 2026-05-09 13:47:04 +02:00
Owner

When creating a record (struct) instance from Java, the fields can be set from the constructor. Fields that require memory allocation, use an Arena, as does allocating the struct itself. When no arena parameter is set, Arena.ofAuto() is used. However, the fields used an Arena.ofAuto() that immediately became unreachable, and the allocated memory too (it is allocated in native code, and assigned in the field's VarHandle, but the MemorySegment is not stored in Java). As a result, the allocated memory for the field was released after the next GC run.

The fix is to use one arena to allocate memory for the struct and the fields. The struct MemorySegment is stored in Java, so the arena is not closed until the Java object is garbage-collected.

One problem that remains, is that re-assigning the field to another value, will allocate a new MemorySegment, but not free the old one. However, this is only the case for parameter allocations in the constructor, and very hard to resolve. If this is an issue, it is better to use the parameterless constructor and set the fields separately.

When creating a record (struct) instance from Java, the fields can be set from the constructor. Fields that require memory allocation, use an Arena, as does allocating the struct itself. When no arena parameter is set, `Arena.ofAuto()` is used. However, the fields used an `Arena.ofAuto()` that immediately became unreachable, and the allocated memory too (it is allocated in native code, and assigned in the field's `VarHandle`, but the `MemorySegment` is not stored in Java). As a result, the allocated memory for the field was released after the next GC run. The fix is to use one arena to allocate memory for the struct and the fields. The struct `MemorySegment` is stored in Java, so the arena is not closed until the Java object is garbage-collected. One problem that remains, is that re-assigning the field to another value, will allocate a new `MemorySegment`, but not free the old one. However, this is only the case for parameter allocations in the constructor, and very hard to resolve. If this is an issue, it is better to use the parameterless constructor and set the fields separately.
jwharm merged commit ba53dba74d into main 2026-05-09 13:47:04 +02:00
jwharm deleted branch fix-record-arena 2026-05-09 13:47:14 +02:00
Sign in to join this conversation.
No description provided.