How to properly cache Bridj JNI objects in Java/Scala

185 Views Asked by At

I'm looking for some guidelines on caching and reusing Bridj JNI objects between multiple JNI calls. I found that caching JNI objects vastly speeds up calling C functions over JNI but it also causes some numerical stability issues. Basically, sometimes the same C function with the same arguments produces different results.

I found this page discussing how to cache JNI objects. http://www.latkin.org/blog/2016/02/01/jni-object-lifetimes-quick-reference/

Does anyone do it in BridJ, any hints on how to cache primitives, structs, pointers, etc.?

1

There are 1 best solutions below

0
Daniel Korzekwa On

Generally it is enough to know that java references to all Bridj pointers should be kept, so that they are not collected by JVM Garbage collector. Once it happens, Bridj/JNI will release the memory allocated for these pointers.

One particular situation to take care of is this: Imagine you create a Java instance of auto generated(with JNAerator) class:

@Library("libtarget.so")
public class SomeStruct extends StructObject {
  public SomeStruct() {
    super();
  }

  @Field(0)
  public Pointer<Byte > p0() {
    return this.io.getPointerField(this, 0);
  }

  @Field(0)
  public SomeStruct p0(Pointer<Byte > p0) {
    this.io.setPointerField(this, 0, p0);
    return this;
  }
...
}

and then

val struct = new SomeStruct()
struct.p0(pointerToCString("a"))

It is not enough to keep a reference to the struct object, also a reference to pointerToCString("a") should be maintained separately. If not, Bridj/JNI will release allocated memory once this pointer is collected by garbage collector. It is not obvious from the code above as it suggests that SomeStruct() object should keep a reference to the pointerToCString("a") pointer anyway.