Search code examples
javamemoryjnajava-memory-model

JMM guarantees about reordering within a try-with-resource & JNI calls


Given the following code sample:

 try (AutoClosable closable = new XXX()) {
      o.method1(closable);  
      o.method2();
 }

Does the Java Memory Model allows HotSpot to reorder closable.close() before o.method2()?

I deliberately ommit implementation details like does method1 captures closable? in the first part of this question.


My spefic use case is this:

I have a C library which can be summarized as:

static char* value;

void capture(char* ptr){
        value = ptr;
}

int len(void) {
    return strlen(value);
}

This native library is wrapped using JNA

interface CApi extends Library {

 static {
   Native.register("test.so", CApi.class)
 }

  void capture(Pointer s);
  int test();
}

And my original client code looks something like this:

cApi = Native.loadLibrary("test.so", CApi.class);


byte[] data = Native.toByteArray("foo");
Memory m = new Memory(data.length + 1);
m.write(0, data, 0, data.length);
m.setByte(data.length, (byte)0);

cApi.capture(m);
System.out.print(cApi.len());

The issue with this first version is that m has been allocated from Java and the lifecycle of this memory is tied to m being strongly reachable. m is no longer strongly reachable once capture(m) and memory will be freed when GC kicks in (JNA relies on finalize to free native memory)

To prevent this I proposed to subclass JNA's Memory to introduce an AutoClosableMemory. The idea is that using a try-with-resource construct would clearly state that the resource is strongly reachable within this scope. The bonus being that we could free the native memory has soon as we no longer need it rather than having to wait for a GC (hey that's RAII!).

try (AutoClosableMemory m = [...]) {
  cApi.capture(m);
  cApi.test();
}

Am I guaranteed that m.close() will never be invoked before cApi.test() and that m is strongly reachable? In this case m is captured by the underlying C API but the java compiler has no way to know it.


Solution

  • In theory, the JVM could reorder the instructions but the outcome of the method has to remain correct. HotSpot does not understand native code and in order to guarantee correctness, it never reorders code around native instructions.