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有几个设计的原则:
第一、JNIEnv指针被设计成了Thread Local Storage
(TLS)变量,也就是说每一个Thread, JNIEnv变量都有独立的Copy。这样做的原因主要是考虑到:
由于JVM要运行在多个平台(除了主流的Windows,Linux等平台),JNI内部实现
很
多要依赖到TLS, 为了减少对TLS的依赖,所有TLS based的数据都会存放于JNIEnv中。这样相当于只依赖一个TLS
based的变量JNIEnv。由于JNIEnv指针是TLS的,所以你不能把Thead#1使用的JNIEnv传给Thread#2使用。
第
二、JNIEnv中定义了一组函数指针,c/c++ Native程序是通过这些函数指针操纵Java数据。这样设计的好处是:你的c/c++
程序不需要依赖任何函数库,或者DLL。由于JVM可能由不同的厂商实现,不同厂商有自己不同的JNI实现,如果要求这些厂商暴露约定好的一些头文件和
库,这不是灵活的设计。
而且使用函数指针表的另外一个好处是:
JVM可以根据启动参数动态替换JNI实现。比如:类似于C库,JNI实现为了性能起见,并没有对调用者传入的参数进行检查。但是在调试阶段,也许这种检
查是很必要的,帮助你尽早发现BUG。例如如果你使用IBM JDK,你可以指定JVM参数–Xcheck:jni,告诉JVM使用带检查的JNI实现。
参考:
http://java.sun.com/docs/books/jni/html/jniTOC.html
分享到:
相关推荐
Android Studio JNI 的静动态注册开发以及CC++ JNIEnv的理解
Eclipse + vs2013 编写第一个JNI HelloWorld, Java 通过JNI调用C ,通过VS2010生成 dll库,来通过Java调用
JNI_ENV_FUNCTIONS 函数及对应的编码,Android下ARM静态反编译逆向
SourceInsight编辑器常用属性设置,一款常用编辑器
JNIEXPORT jdouble JNICALL Java_com_xxx_hello_HelloJni_add(JNIEnv *env, jobject obj, jdouble a, jdouble b) { return a + b; } JNIEXPORT jdouble JNICALL Java_com_xxx_hello_HelloJni_sub(JNIEnv *env, ...
【Android NDK 开发】JNI 线程 ( JNI 线程创建 | 线程执行函数 | 非 JNI 方法获取 JNIEnv 与 Java 对象 | 线程获取 JNIEnv | 全局变量设置 ) 博客地址 : ...
实现了JNI动态注册和在JNI线程中获取JNIEnv
第一步获得:两个参数 JNIEnv和jclass void Java_com_Test_Audio_Init( JNIEnv* env,jclass cls, jobject thiz ) { InitJNI(env,cls); } bool InitJNI(JNIEnv* env,jclass cls) { m_Env=env; m_cls=
《深入理解Android:卷I》是一本以情景方式对...2.4.4 通过JNIEnv操作jobject / 25 2.4.5 jstring介绍 / 27 2.4.6 JNI类型签名介绍 / 28 2.4.7 垃圾回收 / 29 2.4.8 JNI中的异常处理 / 32 2.5 本章小结 / 32
【Android NDK 开发】JNI 动态注册 ( 动态注册流程 | JNI_OnLoad 方法 | ... ... I ....II ....III ....IV ....V . JavaVM 获取 JNIEnv ( GetEnv ) VI . 动态注册方法 RegisterNatives ( 核心重点 ) VII . 动态注册流程完整代码
可以去掉Qt的依赖jint create_vm(JavaVM** jvm, JNIEnv** env) { JavaVMInitArgs args; JavaVMOption options[1]; args.version = JNI_VERSION_1_6; args.nOptions = 1; options[0].optionString = "-Djava....
请注意代码中的函数JNIEXPORT void JNICALL Java_Test_cls(JNIEnv *env, jobject obj),函数名字的Test是指使用该函数的Java类的类名,cls是java代码使用的清屏函数的函数名。 动态链接库是使用VC++6.0生成的。 具体...
static int registerNatives(JNIEnv* engv) { LOGI("registerNatives begin"); jclass clazz; clazz = (*engv) -> FindClass(engv, "com/dn/tim/dn_lsn_9/FileUtils"); if (clazz == NULL) { LOGI(...
这是 Kotlin 语言编写...这个接口函数的作用是创建新线程,并在新线程中调用 callJavaStaticMethod 方法,这个方法会获取当前线程的 JNIEnv 对象和 Java 类对象,并通过这些对象调用 Java 层的静态方法 staticMethod。
只有两步:1. 获取java函数的信息,classid、methodid等等2. 选择JNIEnv中的接口,进行函数调用getStaticMethodInfo参
在这个例子中,我们使用...注意,我们在实现函数中使用了`JNIEnv *env`和`jobject obj`这两个参数,它们分别表示JNI的环境指针和当前对象的引用。这些参数可以让我们方便地在Java和C++之间传递数据和调用其他本地方法。
#include"TestNative.h"; JNIEXPORT jint JNICALL Java_TestNative_add (JNIEnv *ev, jobject obj, jint x, jint y) { return x+y; }
JNIEXPORT VOID JNICALL Java_ClearScreen_clearScreen(JNIEnv *, jclass) { system("cls"); } 5.安装一个microsoft compiler 编译ClearScreen.cpp,得到Clear.dll 注意:将Jdk安装环境include目录下的jawt_md.h ...
将错误的amr文件修复后并保存。部分代码。 /* DO NOT EDIT THIS FILE - it is machine generated */ #include ... (JNIEnv *env, jobject jot, jstring _path); #ifdef __cplusplus } #endif #endif
jni简单使用 java通过JNI调用c++的简单配置步骤, Java 通过JNI调用c++ 1.java代码: ... class HelloWorld { static { ... (JNIEnv *env, jobject obj){ printf("HelloWorld JNI!/n"); return; }