<div dir="ltr"><div dir="ltr"><div>Hi Maurizio</div><div><br></div><div>Thanks for the prompt answer.</div><div><br></div><div>I can understand that you are reluctant to introduce a new concept for a use cases that isn't particularly frequent.</div><div><br></div><div>From what I read about ScopedValues, I doubt they will be helpful. In many of the use cases I'm dealing with, the void* parameter is used in a cross-thread context and has a lifetime, which is not aligned with a function call or a similar scope. A thread-local variable is not helpful for my use cases. Doesn't this imply that ScopedValues won't help either?</div><div><br></div><div>Regarding JNI handles and resurrection I don't have sufficient insight into the implementation to comment on this. Since it is already possible to bind an object to a method handle, create an upcall stub for it and passed it around in native code, it would seem to me that part of the challenges have already been solved.</div><div><br></div><div>Regards</div><div>Manuel<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am Mi., 15. Feb. 2023 um 00:21 Uhr schrieb Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com">maurizio.cimadamore@oracle.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Manuel,<br>
in principle, it would be doable to expose an API which creates a JNI <br>
handle out of a Java object and exposes it as a MemorySegment so that it <br>
can be passed to native functions. One thing to consider is that if we <br>
started passing Java objects around to native code, then we'd also have <br>
to start worrying about the same objects being "resurrected" in <br>
unexpected places (e.g. created by one classloader, accessed by <br>
another). Some of these issues are the very reasons behind the <br>
classloader restrictions behind System::loadLibrary [1]. Perhaps here, <br>
since the API doing the access is a Java API, it might be possible to <br>
insert some kind of class loader check.<br>
<br>
That said, one of the main reason we did not add any special support for <br>
JNI handles is that, in addition to the workarounds you mention, a new <br>
and more powerful workaround is/will be possible from Java 20: <br>
ScopedValues [2]. That is, you can set up a scoped value, and "bind" it <br>
before the upcall runs (e.g. before you call the corresponding <br>
downcall). The bound value would then be in scope (as a sort of implicit <br>
parameter) inside the upcall code as well. Retrieving a scoped value is <br>
also quite fast (compared e.g. to a ThreadLocal).<br>
<br>
For this reason we'd like to see how using ScopedValues goes before <br>
thinking about adding more ad-hoc machinery to expose JNI handles in Panama.<br>
<br>
Cheers<br>
Maurizio<br>
<br>
[1] - <br>
<a href="https://docs.oracle.com/javase/7/docs/technotes/guides/jni/jni-12.html#libmanage" rel="noreferrer" target="_blank">https://docs.oracle.com/javase/7/docs/technotes/guides/jni/jni-12.html#libmanage</a><br>
[2] - <a href="https://openjdk.org/jeps/429" rel="noreferrer" target="_blank">https://openjdk.org/jeps/429</a><br>
<br>
<br>
On 14/02/2023 18:39, Manuel Bleichenbacher wrote:<br>
> Hi all<br>
><br>
> Many native SDKs allow the caller to pass a void* or long as an <br>
> additional parameter. This parameter is then later provided as a <br>
> reference to the original call, either in the context of a callback <br>
> function call or as an attribute of an operating system object. The <br>
> native SDK will not interpret the parameter in any way, neither as a <br>
> number nor as a pointer. It's up to the caller to know what it represents.<br>
><br>
> Examples are:<br>
><br>
> lParam in Windows' SendMessage() - <br>
> <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage" rel="noreferrer" target="_blank">https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage</a><br>
><br>
> dwNewLong in Windows' SetClassLongPtr() - <br>
> <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclasslongptrw" rel="noreferrer" target="_blank">https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclasslongptrw</a><br>
><br>
> arg in POSIX's pthread_create() - <br>
> <a href="https://pubs.opengroup.org/onlinepubs/000095399/functions/pthread_create.html" rel="noreferrer" target="_blank">https://pubs.opengroup.org/onlinepubs/000095399/functions/pthread_create.html</a><br>
><br>
> refcon in macOS' WritePipeAsync() - <br>
> <a href="https://developer.apple.com/documentation/iokit/iousbinterfaceinterface800/1639539-writepipeasync" rel="noreferrer" target="_blank">https://developer.apple.com/documentation/iokit/iousbinterfaceinterface800/1639539-writepipeasync</a><br>
><br>
> Is there a way to use this from Java for Java objects, i.e. to pass a <br>
> Java object as a void* and later convert the void* back to the Java <br>
> object?<br>
><br>
> Since the FFM API exposes void* as MemorySegments, it would probably <br>
> mean that a MemorySegment could be created encapsulating a reference <br>
> to a Java object, and that the Java object can later be retrieved from <br>
> this MemorySegment.<br>
><br>
> I am aware of two workarounds:<br>
><br>
> - In the context of a callback function, the Java callback function <br>
> can be extended with an additional parameter and then the Java object <br>
> can be bound to it. This function is then used to create the up call <br>
> stub. Since the callback function already contains the reference, the <br>
> void* parameter is no longer needed and can be passed <br>
> MemorySegment.NULL. In my context (I/O processing with several <br>
> thousand functions calls per second), it likely is rather inefficient <br>
> as several thousand upcall stubs will need to be generated by second.<br>
><br>
> - Instead of the Java object, a generated integer key could be passed <br>
> as the void*. The link between the key and the Java object would need <br>
> to be managed in a hash map. Possible, but more of a workaround.<br>
><br>
> Regards<br>
> Manuel<br>
><br>
><br>
><br>
><br>
</blockquote></div></div>