Currently, we attach a native thread to VM before we jump into upcall code, and we later detach when we're done with the upcall.
In cases where the native library creates a thread pool, and keeps hitting upcalls with the same few threads, this scheme puts the VM under an enormous amount of pressure, as these threads are not recognized by the JVM, which will create a new Thread object each time (even though the underlying native thread is the same).
For instance, when experimenting with a Panama-based port of the Fuse library:
https://github.com/skymatic/fuse-panama
We noted that the VM was generating ~450G of memory in j.l.Thread instances which was obviously having a negative impact in terms of performance.
JNR does not suffer from this issue. JNR seem to feature an heuristics so that after a given thread has been attached enough times (1000) it is no longer detached. This works in the long run, although it does create a fair amount of garbage at the beginning of the application lifecycle.