美文网首页
JNI中AttachCurrentThread和DetachCu

JNI中AttachCurrentThread和DetachCu

作者: 咸鱼Jay | 来源:发表于2022-11-18 14:32 被阅读0次

在《Java与CC++交互JNI编程》中有讲过AttachCurrentThreadDetachCurrentThread的使用。

我们知道在jni中我们可以使用pthread或者std::thread创建线程。因为线程并不是从Java环境创建的,所以这时候创建出的线程是没有JNIEnv的。如果需要使用JNIEnv,可以调用JavaVMAttachCurrentThread将当前线程附加到虚拟机。

jint AttachCurrentThread(JNIEnv** p_env, void* thr_args);

AttachCurrentThread可以调用多次,第一次会附加当前线程到虚拟机并返回JNIEnv,之后再调用的时候因为当前线程已经被附加到虚拟机上了,所以就不需要重复附加了,仅仅只返回JNIEnv即可,作用相当于GetEnv

需要注意的是,在线程退出之前我们必须要调用DetachCurrentThread从虚拟机分离当前线程,,不然会造成内存泄露,线程也不会退出。对于native层创建出来的线程,在调用AttachCurrentThread的时候会创建本地引用表,在调用DetachCurrentThread的时候会释放本地引用表。

但是一般我们并不会频繁的调用AttachCurrentThread/DetachCurrentThread,这样效率很低。一般我们在线程的入口函数调用一次AttachCurrentThread,在线程入口函数退出之前调用一次DetachCurrentThread即可。所以一定要手动释放每个本地引用。不然本地引用越来越多,很容易超出最大限制。
下面这个例子很好的演示了AttachCurrentThread/DetachCurrentThread的用法:

#include <jni.h>
#include <pthread.h>
#include <android/log.h>

extern JavaVM *g_vm;
JNIEnv* getEnv();

void* __start_routine(void*) {
    JNIEnv *env1, *env2, *env3, *env4, *env5;
    int ret;

    JavaVMAttachArgs args;
    args.version = JNI_VERSION_1_4;
    args.name = "pthread-test";//给线程起个名字吧,这样在调试或者崩溃的时候能显示出名字,而不是thead-1,thread-2这样的名字。
    args.group = NULL;//java.lang.ThreadGroup的全局引用,作用你懂的。

    //在调用AttachCurrentThread以前,是没有java环境的,所以GetEnv返回的JNIEnv是NULL
    g_vm->GetEnv((void**)&env1,JNI_VERSION_1_4);
    __android_log_print(ANDROID_LOG_DEBUG, "MD_DEBUG", "before AttachCurrentThread env is:%p", env1);

    //调用AttachCurrentThread,将当前线程附加到虚拟机,附加成功后,将会返回JNIEnv
    ret = g_vm->AttachCurrentThread(&env2, &args);
    __android_log_print(ANDROID_LOG_DEBUG, "MD_DEBUG", "do     AttachCurrentThread env is:%p, ret=%d", env2, ret);


    //在调用AttachCurrentThread以后,GetEnv返回了正确的JNIEnv
    g_vm->GetEnv((void**)&env3,JNI_VERSION_1_4);
    __android_log_print(ANDROID_LOG_DEBUG, "MD_DEBUG", "after  AttachCurrentThread env is:%p", env3);

    //再次调用AttachCurrentThread,直接返回JNIEnv,作用相当于GetEnv
    ret = g_vm->AttachCurrentThread(&env4, NULL);
    __android_log_print(ANDROID_LOG_DEBUG, "MD_DEBUG", "retry  AttachCurrentThread env is:%p, ret=%d", env4, ret);

    //从虚拟机分离线程
    g_vm->DetachCurrentThread();

    //在调用DetachCurrentThread以后,GetEnv返回NULL
    g_vm->GetEnv((void**)&env5,JNI_VERSION_1_4);
    __android_log_print(ANDROID_LOG_DEBUG, "MD_DEBUG", "after  DetachCurrentThread env is:%p", env5);
    return NULL;
}

extern "C" JNIEXPORT void Java_com_example_threadtest_PThread_start(JNIEnv *env, jclass clazz) {
    pthread_t thread;
    pthread_create(&thread, NULL, __start_routine, NULL);
}

深入浅出Android NDK之在jni中使用线程
关于JNI开发的一些建议

相关文章

  • JNI中AttachCurrentThread和DetachCu

    在《Java与CC++交互JNI编程[https://www.cnblogs.com/zuojie/p/16335...

  • Android jni

    NDK Windows和linux 环境搭建 JNI函数调用流程,JNI理解和基本数据类型 JNI访问Java中各...

  • JNI介绍和文档

    JNI 简介 JNI是JAVA和C/C++相互调用的桥梁 文档 官方文档 类型映射 Jni中定义了原始类型和jav...

  • JNI 编程

    1、什么是JNI? 为什么需要JNI? JNI是一种本地编程接口。它允许运行在JAVA虚拟机中的JAVA代码和用其...

  • JNI数组操作

    在JNI中,java的基本数据类型可以直接与jni基本类型映射,但数组作为引用类型不能直接使用和修改,JNI提供了...

  • JNI中jclass和jobject

    jclass和jobject的迷惑第一次使用JNI,实例引用(jobject)和类引用(jclass)让人觉得很困...

  • JNI与底层调用1

    JNI开发系列阅读 JNI与底层调用1 JNI与底层调用2 C/C++在Android开发中的应用 1. JNI ...

  • Android NDK(二)- JNI 基础

    JNI 类型 JNI 中有许多和 Java 相对应的类型 Java 类型JNI 类型booleanjboolean...

  • 3-ndk学习之jni基础篇(3)

    jni多线程操作 这里的效果是在jni中开启子线程,然后在子线程直接调用Activity的方法jni中,jvm是跨...

  • JNI 调用 JAVA 接口

    JNI 调用 JAVA 接口 介绍 JNI 是本地语言编程接口。它允许运行在JVM中的Java代码和用C、C++或...

网友评论

      本文标题:JNI中AttachCurrentThread和DetachCu

      本文链接:https://www.haomeiwen.com/subject/jqmuxdtx.html