JNI系列(3):如何得到JavaVM,JNIEnv接口

在系列(1)中讲到,Java与native code的操作有两种方式:(1)在Java中加载动态链接库(2)使用JNI Invocation inteface,在native code中创建JVM

JavaVM接口
第一种方式,在加载动态链接库的时候,JVM会调用JNI_OnLoad(JavaVM* jvm, void* reserved)(如果定义了该函数)。第一个参数会传入JavaVM指针。

第二种方式,在native code中调用JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)可以得到JavaVM指针。

两种情况下,都可以用全局变量,比如JavaVM* g_jvm来保存获得的指针以便在任意上下文中使用。

Android系统是利用第二种方式Invocation interface来创建JVM的。

JNIEnv接口
JNI开发最常见的错误就是滥用了JNIEnv接口。需要强调的是JNIEnv是跟线程相关的。

在native method中,JNIEnv作为第一个参数传入。那么在JNIEnv不作为参数传入的时候,该如何获得它?JNI提供了两个函数:(jvm)->AttachCurrentThread(jvm, (void*)&env, NULL)和(jvm)->GetEnv(jvm, (void*)&env, JNI_VERSION_1_2)。两个函数都利用JavaVM接口获得JNIEnv接口,上面已经讲到如何获得JavaVM接口。

JNI规范也说明,可以将获得JNIEnv封装成一个函数。

JNIEnv* JNU_GetEnv()

{   

    JNIEnv* env;

    (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_2);

    return env;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++函数封装成 JNI 接口并在 Java 中调用的完成流程如下: 1.编写 C++ 函数,实现想要的功能。 2.通过 JNI 定义该函数的接口,也就是用 JNI 的语法来描述该函数的输入和输出参数。 3.在 JNI 接口中将 C++ 函数名和接口绑定起来,使其成为一个名为“本地方法”的 JNI 函数。这一步通常需要在一个特定的函数中使用 RegisterNatives() 函数进行注册。 4.将编写好的 JNI 接口动态链接到 Java 虚拟机中。这一步可以通过在 Java 中使用 System.loadLibrary 或 System.load 方法来完成。 5.在 Java 中通过 JNI 接口调用 C++ 函数。 具体流程如下: 1.编写 C++ 函数,例如: ```C++ #include <iostream> #include <jni.h> using namespace std; JNIEXPORT void JNICALL Java_MyClass_PrintHello(JNIEnv *env, jobject obj) { cout << "Hello, World!" << endl; } ``` 2.通过 JNI 定义该函数的接口,例如: ```C++ JNIEXPORT void JNICALL Java_MyClass_PrintHello(JNIEnv *env, jobject obj); ``` 3.在 JNI 接口中将 C++ 函数名和接口绑定起来,例如: ```C++ static const JNINativeMethod methods[] = { {"PrintHello", "()V", (void*)Java_MyClass_PrintHello}, }; jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } jclass clazz = env->FindClass("MyClass"); env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])); return JNI_VERSION_1_6; } ``` 4.将编写好的 JNI 接口动态链接到 Java 虚拟机中,例如: ```Java public class MyClass { static { System.loadLibrary("MyLibrary"); } public static native void PrintHello(); } ``` 5.在 Java 中通过 JNI 接口调用 C++ 函数,例如: ```Java public class Main { public static void main(String[] args) { MyClass.PrintHello(); } } ``` 这样,当 Java 调用 MyClass.PrintHello() 方法时,就会通过 JNI 调用 C++ 函数,输出 "Hello, World!"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值