Search code examples
javacperformancestaticjava-native-interface

Is it bad to create static global variable in JNI implementations?


I am new to JNI, so the answer to this naive question might be simply yes.

The problem at hand is that I'm implementing JNI binding to some C library to do heavy lifting work.

Before doing the actual computation, the C library needs to load an auxiliary data structure from shared memory first (and returns a pointer to the "big" struct), or loads from the disk via the provided path if the struct is not available in shared memory.

The auxiliary struct will be used as const.

To avoid loading from disk every time, what I am thinking about is to create a static int that signals the big struct has been properly initialized:

static int big_struct_loaded_in_mem = 0;

void Java_className_dowork(/*parameters*/){
    if(!big_struct_loaded_in_mem){
        // load struct
        big_struct_loaded_in_mem = 1;
    }
    // load from shared mem then do work using big_struct
    load_from_shm();
}

void Java_className_cleanup(/*parameters*/){
    //free up mem
    big_struct_loaded_in_mem = 0;
}

To make things simple, assume that the Java caller and the native function are single-threaded.

Thank you very much!

Note: Of course, a simple fix without the static int might be just call load_from_shm() every time and test the returned pointer, but I am curious if this particular thought is bad: i.e. to make a static global variable in JNI binding.


Solution

  • Yes you should avoid global statics in JNI.

    Java may load multiple instances of a class (because for instance there are multiple classloaders) and the static would be shared amongst all of them. Unfortunately, so would the cleanup call, leading to inconsistency if one of the instances of your class were destroyed while the other was still in use.

    It would be smarter to make use of a native class constructor / finalizer and allocate/deallocate memory resources at those times. This also allows for use cases such as different configurations depending on which ClassLoader loaded your class -- for instance in an EJB Application Container.

    To make things simple, assume that the Java caller and the native function are single-threaded.

    Bad assumption. The JVM does many things behind the scenes.