This discussion is archived
4 Replies Latest reply: Jan 18, 2012 9:11 PM by EJP RSS

Correct JNI_OnLoad JNI_OnUnLoad approach for cacheing jvm ref?

Sreram Newbie
Currently Being Moderated
Currently am successful in calling a C API from Java. What am basically trying to do here is catch an event in C program, and callback the Java instance, to handle it in my Java code (Similar to a event handling in Swing).

I have implemented the event handling in Windows in C, and will be implementing it soon for Linux and Mac, but how do I cache jvm reference? As far as i searched in other forums, I realize the need for implementing JNI_OnLoad and JNI_OnUnLoad functions in C.

But am a bit confused in the concept of global references.

JavaVM *cached_jvm;

JNIEXPORT jint JNICALL myJavaClassCallback() {
jclass Class_myclass;
jmethodID MID_myclass_mymethod;
#ifdef JNI_VERSION_1_2
res = (*cached_jvm)->AttachCurrentThread(cached_jvm, (void**)&env, NULL);
#else
res = (*cached_jvm)->AttachCurrentThread(cached_jvm, &env, NULL);
#endif
if (res < 0) {
printf("Attach failed\n");
return;
}
Class_myclass = (*env)->FindClass(env, "mypackage.MyClass");
if (Class_myclass == NULL) {
goto detach;
}
MID_myclass_mymethod = (*env)->GetStaticMethodID(env, Class_myclass, "myMethod", "(Z)V");
if (MID_myclass_mymethod == NULL) {
goto detach;
}
jboolean jbool = JNI_FALSE;
(*env)->CallStaticVoidMethod(env, cls, MID_myclass_mymethod, jbool);//Correct?
detach:
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}
(*jvm)->DetachCurrentThread(jvm);
}


JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM jvm, void reserved) {
JNIEnv *env;
cached_jvm = jvm; /* cache the JavaVM pointer */

if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
return JNI_ERR; /* JNI version not supported */
}
return JNI_VERSION_1_2;
}


JNIEXPORT void JNICALL JNI_OnUnload(JavaVM jvm, void reserved) {
//Should i implement some delete reference here???
}

I have two questions here.

One, should i call some delete reference (or some function like deleteallrefereces (??)[if available]) on JNI_OnUnload?
And two is my passing of jboolean argument correct?

Thanks,
Sreram
  • 1. Re: Correct JNI_OnLoad JNI_OnUnLoad approach for cacheing jvm ref?
    Sreram Newbie
    Currently Being Moderated
    And one more thing. Am using Java SE6. so should i put JNI_VERSION_1_6 or JNI_VERSION_1_2 will work?
  • 2. Re: Correct JNI_OnLoad JNI_OnUnLoad approach for cacheing jvm ref?
    EJP Guru
    Currently Being Moderated
    But am a bit confused in the concept of global references.
    You're not using global references. Your question?
    One, should i call some delete reference (or some function like deleteallrefereces (??)[if available]) on JNI_OnUnload?
    No.
    And two is my passing of jboolean argument correct?
    Yes, but you don't actually need the variable, just pass JNI_FALSE directly as the argument.
    should I put JNI_VERSION_1_6
    Yes, if there is such a thing.
    or JNI_VERSION_1_2 will work?
    Yes.
  • 3. Re: Correct JNI_OnLoad JNI_OnUnLoad approach for cacheing jvm ref?
    Sreram Newbie
    Currently Being Moderated
    <quote>
    You're not using global references. Your question?
    </quote>
    Oops! I realize now am not using global references. But i have two questions regarding global and local references.

    One, If we create a global reference, and use it in our program, how and when do we delete the reference? When, the answer might be after the reference is no longer in use, but if the reference is used all over the c code, should we delete it manually using DeleteGlobalRef in Unload function? Should DeleteLocalRef be called in every method, where the reference might be used?

    And two, why the code

    <quote>
    static jclass stringClass = NULL;
    jmethodID cid;
    jcharArray elemArr;
    jstring result;
    if (stringClass == NULL) {
    stringClass = (*env)->FindClass(env,"java/lang/String");
    if (stringClass == NULL) {
    return NULL; /* exception thrown */
    }
    }
    /* It is wrong to use the cached stringClass here, because it may be invalid. */
    cid = (*env)->GetMethodID(env, stringClass, "<init>", "([C)V");
    }
    </quote>
    is wrong? I understand the above code is wrong as the stringClass variable here may become invalid and Garbage collector might have removed the variable from memory, but what i don't understand is how will it become invalid when the variable is still used in the same method?

    <quote>No.</quote>

    I understand i mustn't delete any references as i haven't used any global references, but my question was regarding the local and global references i stated above.
    <quote>Yes, but you don't actually need the variable, just pass JNI_FALSE directly as the argument.</quote>

    I knew it. But just wanted to confirm as in my actual code, i will be passing boolean argument based on the condition i determine, at runtime.

    <quote>Yes, if there is such a thing. Yes.</quote>

    The reason i asked this question is, I am using 1.6 version, but am giving 1.2 .. Is it like it will compare with version 1.2 and return true if version is 1.2 or higher?
  • 4. Re: Correct JNI_OnLoad JNI_OnUnLoad approach for cacheing jvm ref?
    EJP Guru
    Currently Being Moderated
    One, If we create a global reference, and use it in our program, how and when do we delete the reference?
    When you've finished with it.
    When, the answer might be after the reference is no longer in use, but if the reference is used all over the c code, should we delete it manually using DeleteGlobalRef in Unload function?
    Not really, the entire JVM is being unloaded, it's probably already too late.
    Should DeleteLocalRef be called in every method, where the reference might be used?
    Only if you're trying to limit local references. See the discussion in the JNI Specification. All local references are released when your JNI method exits.
    And two, why the code
    ...
    is wrong?
    It's a local reference, so it's only valid throughout a single JNI call. To reuse across JNI calls, make a GlobalRef or weak global ref out of it, or reacquire it every time you need it.
    how will it become invalid when the variable is still used in the same method?
    It won't. It can become invalid between methods.
    The reason i asked this question is, I am using 1.6 version, but am giving 1.2 .. Is it like it will compare with version 1.2 and return true if version is 1.2 or higher?
    It will return true if it can support that version. It can.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points