关于JNI里面的一点疑惑

什么是JNI ? JNI就是java和C/C++的交互接口。

最近在复习JNI的使用,之前也用过,都是边学边用,里面很多东西没有仔细理解过。

先贴上JNI代码

//
// Created by fengcheng.cai on 2023/12/15.
//
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES

#include "com_sprd_opengl_test_MyNdk5.h"
#include <ggl.h>
#include <string.h>
#include <unistd.h>
#include <android/bitmap.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#define LOG_TAG "MyNdk5"

struct fileds_t {
    jfieldID mMyNdk5;
    jfieldID mMyNdk6;
    jmethodID mFunc;
};

fileds_t fileds;
jobject gJavaObj = nullptr;

JNIEXPORT void JNICALL Java_com_sprd_opengl_test_MyNdk5_init
        (JNIEnv *env, jobject obj, jobject surface) {
    LOGD("init env: %p, obj: %p", env, obj);
    gJavaObj = env->NewGlobalRef(obj);
}

JNIEXPORT void JNICALL Java_com_sprd_opengl_test_MyNdk5_process
        (JNIEnv *env, jobject obj, jobject bitmap,  jint surfaceW, jint surfaceH) {
    LOGD("process env: %p, obj: %p", env, obj);
    if (env->IsSameObject(gJavaObj, obj)) {
        LOGD("process is same");
    }
}

JNIEXPORT void JNICALL Java_com_sprd_opengl_test_MyNdk5_process2
         (JNIEnv *env, jobject obj) {
    jlong n5 = env->GetLongField(obj, fileds.mMyNdk5);
    jlong n6 = env->GetLongField(obj, fileds.mMyNdk6);
    LOGD("process2 env: %p, obj: %p", env, obj);
    LOGD("process2 n5: %ld, n6: %ld", n5, n6);

    if (env->IsSameObject(gJavaObj, obj)) {
        LOGD("process2 is same");
    }

    env->SetLongField(obj, fileds.mMyNdk5, 88);
    env->SetLongField(obj, fileds.mMyNdk6, 889);

    env->CallVoidMethod(obj, fileds.mFunc, 73, 98);
}

JNIEXPORT void JNICALL Java_com_sprd_opengl_test_MyNdk5_process3
        (JNIEnv *env, jobject obj) {
    LOGD("process3 env: %p, obj: %p", env, obj);
    if (env->IsSameObject(gJavaObj, obj)) {
        LOGD("process3 is same");
    }
}

JNIEXPORT void JNICALL Java_com_sprd_opengl_test_MyNdk5_process4
    (JNIEnv *env, jobject obj) {
    LOGD("process4 env: %p, obj: %p", env, obj);

    if (env->IsSameObject(gJavaObj, obj)) {
        LOGD("process4 is same");
    }
}

JNIEXPORT void JNICALL Java_com_sprd_opengl_test_MyNdk5_uninit
        (JNIEnv *env, jobject obj) {
    jlong n5 = env->GetLongField(obj, fileds.mMyNdk5);
    jlong n6 = env->GetLongField(obj, fileds.mMyNdk6);
    LOGD("uinit env: %p, obj: %p", env, obj);
    LOGD("uinit n5: %ld, n6: %ld", n5, n6);

    env->CallVoidMethod(obj, fileds.mFunc, 72, 99);
}

jint JNI_OnLoad(JavaVM *jvm, void * reserved) {
    JNIEnv *env = nullptr;
    jvm->GetEnv((void**)&env, JNI_VERSION_1_4);

    jclass clazz = env->FindClass("com/sprd/opengl/test/MyNdk5");
    fileds.mMyNdk5 = env->GetFieldID(clazz, "mMyNdk5", "J");
    fileds.mMyNdk6 = env->GetFieldID(clazz, "mMyNdk6", "J");
    fileds.mFunc = env->GetMethodID(clazz, "callback", "(IJ)V");

    LOGD("JNI_OnLoad env: %p", env);
    LOGD("fileds.mMyNdk5: %p", fileds.mMyNdk5);
    LOGD("fileds.mMyNdk6: %p", fileds.mMyNdk6);
    return JNI_VERSION_1_4;
}

我的疑问是jni接口的第二个参数jobject到底是什么?

网上也搜索过问题的答案,都说jobject是java对象,但是我打jobject的地址发现,即使 同一个线程,不同的方法打印的jobject地址都是不一样的

以下是日志打印

 pid       tid
22156-22156//MyNdk5: JNI_OnLoad env: 0xb400007076b8e1d0
22156-22156//MyNdk5: fileds.mMyNdk5: 0xf
22156-22156//MyNdk5: fileds.mMyNdk6: 0x11
22156-22156//MyNdk5: java construct this: com.sprd.opengl.test.MyNdk5@bcd3074
22156-22193//MyNdk5: init env: 0xb400007076b9baf0, obj: 0x6fcc9c4028
22156-22193//MyNdk5: process env: 0xb400007076b9baf0, obj: 0x6fcc9c4008
22156-22193//MyNdk5: process is same


22156-22156//MyNdk5: process2 env: 0xb400007076b8e1d0, obj: 0x7ff0260778
22156-22156//MyNdk5: process2 n5: 19, n6: 97
22156-22156//MyNdk5: process2 is same
22156-22156//MyNdk5: java callback i: 73, j: 98,  this: com.sprd.opengl.test.MyNdk5@bcd3074
22156-22156//MyNdk5: _process2 mMyNdk5: 88, mMyNdk6: 889
22156-22193//MyNdk5: uinit env: 0xb400007076b9baf0, obj: 0x6fcc9c4028
22156-22193//MyNdk5: uinit n5: 88, n6: 889
22156-22193//MyNdk5: java callback i: 72, j: 99,  this: com.sprd.opengl.test.MyNdk5@bcd3074
22156-22156//MyNdk5: process3 env: 0xb400007076b8e1d0, obj: 0x7ff0260b78
22156-22156//MyNdk5: process3 is same
22156-22156//MyNdk5: process4 env: 0xb400007076b8e1d0, obj: 0x7ff0261048
22156-22156//MyNdk5: process4 is same

可以看到,大部分情况jobject是互不相同的,既然它是java对象,而JNI native方法所在的java对象就一个,为啥每次不一样呢?

后来使用 env->IsSameObject 比较了一下发下是一样的,具体原理也不清楚,希望懂的朋友指点一下。

  • 25
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JNI中读写文件可以使用C/C++的文件操作函数来实现,比如fopen、fread、fwrite、fclose等。 以下是一个简单的示例,展示如何在JNI中读取一个文本文件并将其内容打印到Logcat中: ```c++ #include <jni.h> #include <stdio.h> #include <android/log.h> #define TAG "FileIOJNI" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) JNIEXPORT void JNICALL Java_com_example_FileIO_readFile(JNIEnv *env, jobject obj, jstring filename) { const char *file_name = env->GetStringUTFChars(filename, NULL); FILE *file = fopen(file_name, "r"); if (file == NULL) { LOGD("Error opening file '%s'", file_name); return; } char buffer[1024]; while (fgets(buffer, sizeof(buffer), file) != NULL) { LOGD("%s", buffer); } fclose(file); env->ReleaseStringUTFChars(filename, file_name); } ``` 在此示例中,我们使用了fopen函数打开了一个文本文件,使用fgets函数逐行读取文件内容,并将每行内容通过Logcat输出。最后,我们使用fclose函数关闭文件。 类似地,我们可以使用fwrite函数来写入文件,示例如下: ```c++ JNIEXPORT void JNICALL Java_com_example_FileIO_writeFile(JNIEnv *env, jobject obj, jstring filename, jstring content) { const char *file_name = env->GetStringUTFChars(filename, NULL); const char *file_content = env->GetStringUTFChars(content, NULL); FILE *file = fopen(file_name, "w"); if (file == NULL) { LOGD("Error opening file '%s'", file_name); return; } fwrite(file_content, strlen(file_content), 1, file); fclose(file); env->ReleaseStringUTFChars(filename, file_name); env->ReleaseStringUTFChars(content, file_content); } ``` 在此示例中,我们使用了fopen函数打开了一个文本文件,使用fwrite函数将内容写入文件,并使用fclose函数关闭文件。注意,我们使用了strlen函数来获取字符串的长度,并将其作为参数传递给fwrite函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值