JNI received outer class this instead of inner class this in inner class method

63 Views Asked by At

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);
}
0

There are 0 best solutions below