Feature requests.
Per-Ake Minborg
per-ake.minborg at oracle.com
Mon May 19 13:18:54 UTC 2025
Hi again Lee!
1.
The VM/GC has its own rules for how arrays are allocated, and so, there is no way (at least not now) to control primitive array alignment except for the way you mentioned — a primitive array is always aligned to its component's natural alignment. A very simple way to allocate and align heap arrays could be to implement a method similar to this one:
static MemorySegment heapSegment(MemoryLayout layout) {
byte[] arr = new byte[(int) layout.byteSize() * (int)layout.byteAlignment() - 1];
SegmentAllocator allocator = SegmentAllocator.slicingAllocator(MemorySegment.ofArray(arr));
return allocator.allocate(layout);
}
If memory efficiency is a concern, a more complex solution can be written that leverages the implicit alignment of arrays of int and long.
2.
The Arena interface is not sealed. So, anyone can write their implementation that typically delegates to one of the out-of-the-box Arena types provided by the JDK. The question then becomes: What arena type should such a bespoke Arena return? I am not sure why you need to be able to determine the Arena type, but there are some (legal) tricks that can be used:
*
If the arena is identical to Arena.ofGlobal(), then the arena type is global (as there is, by definition, only one Global arena).
*
If, on another (private) thread, invoking isAccessibleBy(Thread thread) returns false, on a segment allocated from the arena, it is a Confined Arena or a bespoke Arena, which delegates to a Confined Arena.
There are other hacky ways (that are not future-proof) to figure out the arena type that I do not want to mention here. Maybe someone else can come up with a clever way to legally figure out the rest without closing the arena? What is the use case for this? Maybe it is related to 3.? If you have full control of your application, I suggest that you implement your own arena type. I do not see any safety implications with this.
3.
The non-idempotency of the close()operation was discussed on several occasions during the design process of the FFM API. The choice was deliberate, as not knowing if an arena should be closed or not often reveals subtle edge cases in the code (e.g., a resource is transferred to another owner, but the original owner is unaware of this). Again, you can create your own arena that has an idempotent close operation or adds a tryClose() operation that returns if/if not the arena was closed:
if (arena instanceof MyArena ma) {
ma.tryClose();
}
As a blunt last resort, you can always catch the exception of a failed close() operation.
Adding a tryClose() operator to the API would raise compatibility issues with bespoke implementations of the Arena interface, which are already out in the wild. Adding a default tryClose() method might, in such cases, depend on catching exceptions, which is slow if an exception is actually thrown.
I am not sure my answer to this last bullet meets your expectations, but I hope you might be able to pick up some ideas.
Best, Per Minborg
________________________________
From: panama-dev <panama-dev-retn at openjdk.org> on behalf of Lee Rhodes <leerho at gmail.com>
Sent: Friday, May 16, 2025 1:35 AM
To: panama-dev at openjdk.org <panama-dev at openjdk.org>
Subject: Feature requests.
I'm not sure this is the right forum for this. Let me know if this should be directed elsewhere. 🙂
1. Easier memory alignment when creating segments on-heap.
Our library wants to treat on-heap and off-heap MemorySegments identically. But there is asymmetry in the APIs for creating segments on-heap vs off-heap.
Currently the only way, that I am aware of, to ensure that an on-heap segment is created with the proper alignment is to create it with an primitive array of the desired natural alignment. For example, suppose I want to create an on-heap segment of a 9 byte struct consisting of a long and a byte. If I want the long to be properly memory aligned, I have to allocate the on-heap segment with MemorySegment.ofArray(new long[2]) instead of MemorySegment.ofArray(new byte[9]).withAlignment(8), which would be much more natural and convenient, particularly with more complex structs. The effective memory usage of these two approaches is probably the same. So this request is not for memory efficiency, per se.
Suppose I need to access pairs of doubles (e.g., complex numbers, or 128-bit floating point values) and I would like these objects to be memory aligned to 16 bytes. That is easy to do off-heap, but how would I do that on-heap?
2. Accessible configuration parameters for Arena.
It would be useful to be able to determine the type of a given Arena. For example, given an Arena, is it Global, Auto, Confined or Shared? A simple getArenaType() would work. To do this today I would have to extend Arena, with a separate tracking variable for the type created, but it is unclear to me if that extended arena would provide the same "strong thread-safety, lifetime and non-overlapping guarantees".
3. An idempotent option to close an Arena.
Having an additional idempotent Arena::close() option such as an Arena::closeIfCloseable() method. This would check if the type of arena can be closed (see above) and if the arena is alive, and, if true, would atomically (thread-safe) close the arena.
The reason for this request is that in large systems the knowledge that a resource can be closed can be quite remote from the application, process, or code that allocated the resource. Given that there may be multiple Arenas active in a system it would be convenient to have a common method that would close any Arena, if it is closeable, without throwing exceptions. Given the current design, a system must separately track each Arena and its type, and conceivably have to separately track every MemorySegment allocated by each Arena and the state of each segment.
The API Note in the Close() documentation states:
This operation is not idempotent; that is, closing an already closed arena always results in an exception being thrown. This reflects a deliberate design choice: failure to close an arena might reveal a bug in the underlying application logic.
The design decision to make it not idempotent seems to be presumptive given the rationale that "failure to close an arena might reveal a bug ...", and there are no other alternatives. Because it might not reveal a bug in the application logic.
I'm not suggesting any change to the current close() method. This is a request for an idempotent alternative.
I'm expecting 1) vociferous disagreement on this one 🙂, or 2) at least a more comprehensive rationale as to why the ability to close arenas is so limited.
Cheers,
Lee.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20250519/177247f1/attachment-0001.htm>
More information about the panama-dev
mailing list