Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Java layer object be released by JNI?

I create a Java object by calling native code which return a jobject value.

Java code:

Object myObj = nativeCreateObject();

Native code:

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

my question is: whether I can use hold_ref later to release the myObj by reference in native layer? e.g. native code:

*hold_ref = NULL;

Then the myObj in Java layer is null? if not, how can I release this object by native code?

like image 721
ignorer Avatar asked Dec 11 '25 04:12

ignorer


1 Answers

I am not sure, what you want to achieve, but here is how it basicly works:

whether I can use hold_ref later to release the myObj by reference in native layer?

Yes, you can and should use env->DeleteGlobalRef(myObj) to free the global reference you have created so the garbage collector can clean up and finaly destroy the object.

Then the myObj in Java layer is null? if not, how can I release this object by native code?

There is no way your Java-variable will turn null magicaly when you delete the reference from jni native code. Java itself holds a reference to prevent the object is removed by the garbage collection.

You may want to use it this way:

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 in someway I suggest to manage the state and throw an exception, if the object was invalidated 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
    }
}

Simply call invalidate() on your object from native code to prevent it from being used anymore.

like image 135
Myon Avatar answered Dec 14 '25 03:12

Myon