Can Java object be JNI released?

I am creating a Java object by calling native code that returns a job value.

Java code:

Object myObj = nativeCreateObject();

      

Source:

jobject* hold_ref;
JNIEXPORT jobject JNICALL
nativeCreateObject(JNIEnv *env ...) {
    .....
    result = env->NewGlobalRef(jobj);
    hold_ref = &result;
    return result;
}

      

My question is, can I use hold_ref later to free myObj by reference in its own layer? for example native code:

*hold_ref = NULL;

      

Then myObj in Java layer is null? if not, how can I free this object with my own code?

+3


source to share


1 answer


I'm not sure what you want to achieve, but this is how it works:

can i use hold_ref later to free myObj by reference in its own layer?

Yes, you can and should use env->DeleteGlobalRef(myObj)

to free the global reference you created so that the garbage collector can clean up and permanently destroy the object.

Then myObj in Java layer is null? if not, how can I free this object with my own code?

It is not possible for your Java variable to go back to zero magic when removing a reference from jni's native code. Java itself contains a link to prevent garbage collection of an object.

You can use it like this:

C ++



jobject* hold_ref;

JNIEXPORT jobject JNICALL nativeCreateObject(JNIEnv *env ...) {
   .....
   result = env->NewGlobalRef(jobj);
   hold_ref = &result;
   return result;
}

JNIEXPORT void JNICALL nativeDestroyObject(JNIEnv *env ...) {
   .....
   env->DeleteGlobalRef(jobj);
   hold_ref = nullptr;
}

      

JAVA

// Creates two references (native and local variable)
Object myObj = nativeCreateObject();

// Deletes the native reference, but not the local one
nativeDeleteObject(myObj);
// myObj != null

myObj = null;
// now there is no reference to your created object
// the garbage collector may destroy it any time

      

If you want to invalidate your object somehow, I suggest managing the state and throwing an exception if the object was invalid like this:

class MyInvalidateableObject {

    private boolean invalidated = false;

    public void invalidate() {
        this.invalidated = true;
    }

    public void foo() {
        if (invalidated) 
            throw new IllegalStateException("Object has been invalidated");
        ... // do the normal stuff
    }
}

      

Just call invalidate()

your object from your own code so that it is no longer used.

+2


source







All Articles