I've two classes: OuterClass
and InnerClass
inside.
JNI received outer class this instead of inner class this in inner class method
public final class OuterClass {
static {
System.loadLibrary("jtest");
}
private native void jni_print(Object obj);
static private void print(Object o1, Object o2) {
System.out.println("this = " + o1 + ", arg1 = " + o2);
}
public OuterClass() {
}
public void printThis() {
jni_print(this);
}
public final class InnerClass {
public InnerClass() {
}
public void printThis() {
jni_print(this);
}
}
}
I create one instance of OuterClass
and inside one instance of InnerClass
and execute printThis
function:
class Main {
public static void main(String[] args) throws InterruptedException {
OuterClass oc = new OuterClass();
OuterClass.InnerClass ic = oc.new InnerClass();
oc.printThis();
ic.printThis();
}
}
As a result I get this:
this = OuterClass@3764951d, arg1 = OuterClass@3764951d
this = OuterClass@3764951d, arg1 = OuterClass$InnerClass@4b1210ee
As you see, this
is incorrect in the InnerClass method call. Is it intended? Why isn't it documented? Should I pass the handler to this as a parameter?
My JNI is:
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#define JNIT_CLASS "OuterClass"
static void jni_print(JNIEnv *env, jobject this, jobject obj) {
jclass cls = (*env)->FindClass(env, JNIT_CLASS);
jmethodID printID = (*env)->GetStaticMethodID(env, cls, "print", "(Ljava/lang/Object;Ljava/lang/Object;)V");
(*env)->CallStaticVoidMethod(env, cls, printID, this, obj);
}
static JNINativeMethod funcs[] = {
{ "jni_print", "(Ljava/lang/Object;)V", (void *)&jni_print },
};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv *env;
jclass cls;
jint reg_res;
(void)reserved;
if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_8) != JNI_OK)
return -1;
cls = (*env)->FindClass(env, JNIT_CLASS);
if (cls == NULL)
return -1;
reg_res = (*env)->RegisterNatives(env, cls, funcs, sizeof(funcs)/sizeof(funcs[0]));
if (reg_res != 0)
return -1;
return JNI_VERSION_1_8;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
JNIEnv *env;
jclass cls;
(void)reserved;
if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_8) != JNI_OK)
return;
cls = (*env)->FindClass(env, JNIT_CLASS);
if (cls == NULL)
return;
(*env)->UnregisterNatives(env, cls);
}