这里的JavaVM就是虚拟机VM在JNI中的表示,一个进程JVM中只有一个JavaVM对象,这个对象是线程共享的。...就是说JavaVM->GetEnv获取的是,此线程有效的env。JavaVM->AttachCurrentThread是向虚拟机分配线程独立的env。...理论知识介绍到这里,我们继续测试功能函数,现在代码应该是长这样的: JavaVM *javaVM; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void...(javaVM,&env,NULL) // (*javaVM)->GetEnv(javaVM, (void **)&env, JNI_VERSION_1_6) if ( (*javaVM...)->DetachCurrentThread(javaVM); pthread_exit((void *) 0); } 我们在JNI_OnLoad函数全局引用JavaVM对象,然后就是模板代码了
%s",text); env->ReleaseStringUTFChars(value,text); return 200; } JavaVM *javaVm; const char *...dynamicM01)}, {"dynamicJavaM02", "(Ljava/lang/String;)I", (int *) (dynamicM02)}, }; jint JNI_OnLoad(JavaVM...*vm, void *unused) { ::javaVm = vm; JNIEnv *jniEnv = nullptr; int result = javaVm->GetEnv...JNI_VERSION_1_6;// AS的JDK在JNI默认最高1.6 Java的JDKJNI 1.8 } JNI_OnLoad 中赋值我们用了域的方式,如:this.a = a ---> ::javaVm...动态注册核心RegisterNatives ① 重写JNI_OnLoad ② JavaVM 初始化获取JNIEnv,并获取到jclass ③ 注册函数 //RegisterNatives(jclass
JNI_CreateJavaVM(JavaVM **pvm, void **penv, void*args); 1、JavaVM ?...JVM与JavaVM.png 其中JavaVM是Java虚拟机在JNI层的代表,JNI全局仅仅有一个JavaVM结构中封装了一些函数指针(或叫函数表结构),JavaVM中封装的这些函数指针主要是对JVM...JNIEnv是一个线程相关的结构体,该结构体代表了Java在本线程的执行环境 2.2、JNIEnv和JavaVM的区别: JavaVM:JavaVM是Java虚拟机在JNI层的代表,JNI全局仅仅有一个...)(JavaVM, JNIEnv*, void) 方法,能够获得JNIEnv结构体 C++中 ——_JavaVM:_JavaVM是C++中JavaVM结构体,调用jint AttachCurrentThread...中的(DetachCurrentThread)(JavaVM)方法,能够释放本线程的JNIEnv C++ 中释放:调用JavaVM结构体_JavaVM中的jint DetachCurrentThread
经过上面操作后 ijkffmpeg、ijdsdk及ijkplayer就被加载到JavaVM里了。 在Android系统下,每一个进程只能有一个JavaVM。...当然,只做到这一步还无法调用 C/C++接口,因为你还没告诉JavaVM你的C/C++接口在哪儿呢。下面我们开始第二步。 注册C/C++方法 仅在Java层定义本地方法只完成了工作的一半。...当Java代码真正调用 “native” 方法时,JavaVM虚拟机会在自己的符号表中查找有没有 Java 程序想调用的函数。如果此时还没有的话,JavaVM 就会报错。...所以现在我们要将 C/C++ 提供的接口注册到 JavaVM中。 首先,建好函数对应表。此表中的每一项都包括三个元素,分别是 外部调用的接口名、signature、内部真正的实现函数。...在加载动态链接库时,JavaVM会主动调用JNI_OnLoad(JavaVM * jvm, void * reserved)(如果你实现在JNI_OnLoad函数),所以在这里注册是最好的地方。
JavaVM *vm IV . 局部引用 与 全局引用 分析 V . Native 调用 Java 方法 ( 主线程 ) VI . Native 调用 Java 方法 ( 子线程 ) VII ....JavaVM *vm ---- JavaVM *vm 获取方法 : 在 JNI_OnLoad() 方法中获取 ; //JNI_OnLoad 中获取的 Java 虚拟机对象放在这里 JavaVM *javaVM...; int JNI_OnLoad(JavaVM *vm, void *r){ javaVM = vm; return JNI_VERSION_1_6; } JNI_OnLoad 参考...全局引用 : JNIEnv *env 与 JavaVM *vm 本身就是全局引用 , 不用刻意将其转为全局引用 , 可以跨方法跨线程调用 ; 3 ....*javaVM; int JNI_OnLoad(JavaVM *vm, void *r){ javaVM = vm; return JNI_VERSION_1_6; } extern
JNIEnv 作用 JNIEnv 概念 : 是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境 ; JNIEnv 与 JavaVM : 注意区分这两个概念; -- JavaVM...: JavaVM 是 Java虚拟机在 JNI 层的代表, JNI 全局只有一个; -- JNIEnv : JavaVM 在线程中的代表, 每个线程都有一个, JNI 中可能有很多个 JNIEnv; JNIEnv...JNIEnv 的创建和释放 JNIEnv 创建 和 释放 : 从 JavaVM 获得 : 下面是 JavaVM 结构体的代码, -- C语言 中来源 : JNIInvokeInterface 是 C...语言环境中的 JavaVM 结构体, 调用 (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*) 方法, 可以获取 JNIEnv结构体; -- C++ 中来源...: _JavaVM 是 C++ 中的 JavaVM 结构体, 调用 jint AttachCurrentThread(JNIEnv** p_env, void* thr_args) 方法, 可以获取
解决:使用JavaVM,这里先介绍下JNIEnv和JavaVM的概念。...JavaVM:Java虚拟机在Native层的代表,在Android中一个进程只有一个JavaVM,所有的线程共用一个JavaVM。...到这里大家可能都清楚了,只要能够得到JavaVM就可以解决JNIEnv的问题,那如何获取JavaVM呢? 如何获取JavaVM? 这里只介绍Android中常见的获取JavaVM的方法。...方法二:通过JNIEnv获取JavaVM,在程序的最开始写一个类似于初始化功能的函数,传到Native层一个可用的JNIEnv,之后就可以获取到JavaVM。...JavaVM *global_jvm; void get_jvm(JNIEnv *env) { env->GetJavaVM(&global_jvm); } 如何通过JavaVM获取JNIEnv?
designa.gif 3 JavaVM 和 JNIEnv JNI 定义了两个关键数据结构,即“JavaVM”和“JNIEnv”。两者本质上都是指向函数表的二级指针。...JavaVM 理论上,每个进程可以有多个 JavaVM,但 Android 只允许有一个。...JavaVM的获取方式: 第一种方式,在加载动态链接库的时候,JVM会调用JNI_OnLoad(JavaVM* jvm, void* reserved)(如果定义了该函数)。...第一个参数会传入JavaVM指针。 第二种方式,在native code中调用JNI_CreateJavaVM(&jvm, (void*)&env, &vm_args)可以得到JavaVM指针。...在C和C++中的JavaVM的定义有所不同,在C中JavaVM是JNIInvokeInterface_类型指针,而在C++中有对JNIInvokeInterface_进行了一次封装 JNIEnv JNIEnv
Zygote简介 在Android系统中,JavaVM(Java虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器。...它通过fock(复制进程)的形式来创建应用程序进程和SystemServer进程,由于Zygote进程在启动时会创建JavaVM,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个...JavaVM的实例拷贝。...,注释2处调用startReg函数用来为JavaVm注册JNI。...2.创建JavaVM并为JavaVM注册JNI. 3.通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层。
获取 JNIEnv JNI 环境 , 需要从 JavaVM 获取 JNIEnv *env = nullptr; //2 ....调用 JavaVM / _JavaVM 结构体的 jint GetEnv(void** env, jint version) 方法 // 返回值分析 : 动态注册会返回一个结果...JavaVM 获取 JNIEnv ( GetEnv ) ---- 函数原型 : 从 Java 虚拟机 ( JavaVM ) 中获取 JNI 运行环境 ( JNIEnv ) ; ① 参数说明 : void...获取 JNIEnv JNI 环境 , 需要从 JavaVM 获取 JNIEnv *env = nullptr; //2 ....调用 JavaVM / _JavaVM 结构体的 jint GetEnv(void** env, jint version) 方法 // 返回值分析 : 动态注册会返回一个结果
::ClassLinker 各个 trampoline 的地址 … 其中的一些是通过结构体的固定偏移来获得,比如 art::Runtime 就在 JavaVM 结构的第二个位置: struct _JavaVM...Runtime* const runtime_; } 用 gdb 也可以进行验证: (gdb) ptype /o JavaVM type = struct _JavaVM { /* 0...*,内存布局如下所示: #ifdef __cplusplus typedef JavaVM_ JavaVM; #else typedef const struct JNIInvokeInterface..._ *JavaVM; #endif struct JavaVM_ { const struct JNIInvokeInterface_ *functions; #ifdef __cplusplus...*DetachCurrentThread)(JavaVM *vm); jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version)
JNINativeInterface* C_JNIEnv; #if defined(__cplusplus) typedef _JNIEnv JNIEnv; typedef _JavaVM JavaVM...熟悉 JavaVM 的结构 在前面已经了解了JNI_OnLoad函数 它会传递一个JavaVM的指针作为参数 通过JavaVM的getEnv函数可以获得JNIEnv对象的指针 JavaVM其实就是_JavaVM...typedef _JNIEnv JNIEnv; typedef _JavaVM JavaVM; 复制代码 既然这样,我们先看下_JavaVM的结构: struct _JavaVM { const...)(JavaVM*); jint (*GetEnv)(JavaVM*, void**, jint); jint (*AttachCurrentThreadAsDaemon...)(JavaVM*, JNIEnv**, void*); }; 复制代码 _JavaVM中定义了一些和虚拟机生命周期相关的方法 方法的实现是通过调用的JNIInvokeInterface functions
JavaVM 是 Java虚拟机在 JNI 层的代表,JNI 全局只有一个;而JNIEnv是 JavaVM 在线程中的代表,每个线程都有一个,JNI 中可能有很多个 JNIEnv。...)(JavaVM*); jint (*GetEnv)(JavaVM*, void**, jint); jint (*AttachCurrentThreadAsDaemon...)(JavaVM*, JNIEnv**, void*); }; /* * C++ version. */ struct _JavaVM { const struct JNIInvokeInterface...)(JavaVM)可以释放本线程中的JNIEnv 对于C++来说: 创建JNIEnv:__JavaVM是C++中的JavaVM结构体,调用jint AttachCurrentThread(JNIEnv*...* C_JNIEnv; #if defined(__cplusplus) typedef _JNIEnv JNIEnv; typedef _JavaVM JavaVM; #else typedef const
JNIEnv 指针 ; ④ 剥离线程 : 注意使用完 JNIEnv 后 , 解绑线程 , 调用 JavaVM 的 DetachCurrentThread 方法 解绑线程 ; 2 ....方法参数中的 JNIEnv 指针是不能跨线程使用的 , 在 主线程中调用 JNI 方法 , 其 JNIEnv 指针不能在子线程中使用 如果在子线程中使用 JNIEnv 指针 , 需要使用 JavaVM...获取 指定线程的 JNIEnv 指针 调用 JavaVM 的 AttachCurrentThread 可以获取本线程的 JNIEnv 指针 注意最后还要将线程从 Java...方法参数中的 JNIEnv 指针是不能跨线程使用的 , 在 主线程中调用 JNI 方法 , 其 JNIEnv 指针不能在子线程中使用 如果在子线程中使用 JNIEnv 指针 , 需要使用 JavaVM...获取 指定线程的 JNIEnv 指针 调用 JavaVM 的 AttachCurrentThread 可以获取本线程的 JNIEnv 指针 注意最后还要将线程从 Java
JavaVM 和 JNIEnv JNI定义了两种重要的数据结构 JavaVM 和 JNIEnv。他们都是指向函数表指针的指针。 JavaVM提供了调用接口的函数,它允许你创建或销毁JavaVM。...理论上在同一个进程中你可以有多个JavaVM,但 Android 只支持一个。 JNIEnv提供了大部分 JNI 函数。你自己的 Native 函数的第一个参数就是 JNIEnv。...如果一段代码无法得到JNIEnv,你应该通过 JavaVM 的 GetEnv 方法获取。 C 声明 JavaVM 和 JNIEev 与 C++ 的声明不一样。...但它可以在任何地方创建,然后再绑定到 JavaVM上。...例如,pthread_create创建的线程,可以通过 AttachCurrentThread 或 AttachCurrentThreadAsDaemon 函数绑到 JavaVM上。
可以看到如下的信息: $ ls -l java lrwxr-xr-x 1 root wheel 74 11 11 15:08 java -> /System/Library/Frameworks/JavaVM.framework...JDK到 /Library/Java/JavaVirtualMachines/jdk{version}.jdk/Content/Home 2.在/System/Library/Frameworks/JavaVM.framework...usr/bin/java* lrwxr-xr-x 1 root wheel 74 11 11 15:08 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework...Commands/java lrwxr-xr-x 1 root wheel 75 11 11 15:08 /usr/bin/javac -> /System/Library/Frameworks/JavaVM.framework...javap lrwxr-xr-x 1 root wheel 82 11 11 15:08 /usr/bin/javapackager -> /System/Library/Frameworks/JavaVM.framework
JNIEnv 和 JavaVM 类型的作用域 JNIEnv 这个结构体比较特殊,主要提供 JNI 调用环境(JNI Environment),JNIEnv 类型的变量是线程相关,即一个线程会对应一个 JNIEnv...//释放 jvm->DetachCurrentThread(); JavaVM 类型的变量是进程相关,即一个 Java 虚拟机对应一个 JavaVM 类型的变量,通过 env->GetJavaVM(&g_jvm...) 可获取当前进程 JavaVM 的指针。...一个简单的例子说明下 JNIEnv 和 JavaVM 类型变量的作用域。...jstring JNICALL Java_com_byteflow_ndk_MainActivity_stringFromJNI(JNIEnv* env, jobject obj) { //获取 JavaVM
Oracle Database Pack 10.2.0.1.0 VALID ages and Types JAVAVM...Oracle Database Pack 10.2.0.1.0 VALID ages and Types JAVAVM.../javavm/install/rmjvm.sql and truncate $java$jvm$status; SQL> select *from obj$ where obj#=0 and type...CATPROC Oracle Database Packages and Types VALID 10.2.0.1.0 JAVAVM.../javavm/install/initjvm.sql 。。。。。。。很多日志。。。。。 SQL>@?/xdk/admin/initxml.sql 。。。。。。。很多日志。。。。 SQL> @?
JavaVM 是 Java虚拟机在 JNI 层的代表, JNI 全局只有一个, 即一个进程只有一个。...解决的方法可以通过JavaVM 的AttachCurrentThread方法去获取当前线程的JNIEnv A JNI interface pointer (JNIEnv*) is passed as an...int status = javaVM->GetEnv((void**)&env, JNI_VERSION_1_4); if (status < 0) { javaVM->AttachCurrentThread...if (status < 0) { javaVM->DetachCurrentThread(); } 4 jobject与jclass类型 object与jclass通常作为JNI...解决的方法是通过全局引用来获取 env->NewGlobalRef(obj) JavaVM *g_jvm = NULL; jobject g_obj = NULL; //由java调用来建立JNI环境
比如我们知道在JNI的API中就有两个重要的结构:JavaVM,JNIEnv a....JavaVM typedef const struct JNIInvokeInterface* JavaVM; 原来JavaVM只是一个JNIInvokeInterface类型的指针 b....JavaVMExt 在代码中,我们经常看到JavaVMExt指针和JavaVM指针的互转,所以顺带说一下,JavaVMExt可以说是JavaVM的扩展,实际上确实如此,可以看到它包含了更多的信息:...)(JavaVM*); jint (*GetEnv)(JavaVM*, void**, jint); jint (*AttachCurrentThreadAsDaemon...)(JavaVM*, JNIEnv**, void*); }; JNIInvokeInterface可以理解为函数表,其中包含了若干操作虚拟机的函数指针。
领取专属 10元无门槛券
手把手带您无忧上云