摘要:初识本地接口概述是用于和本地代码进行交互操作的。针对的是语言,而不是。当然,最初也有运行的比较慢的原因,但随着的不断发展,编写的代码有时已经不逊于一些的代码了。声明通过关键字标识,提醒编译器该方法在外部定义。
初识 JNI
JNI, Java Native Interface(Java本地接口).概述
JNI 是用于和本地 C 代码进行交互操作的API。实际上可以通过许多语言编写,如C++、C#,本质上 Java 调用的是 dll/so 库 。此处说是和本地 C 代码互操作是因为 JNI API的支持。JNI API针对的是 C 语言,而不是Java。
JNI 的出现的原因有一些是为了弥补一些无法通过 Java 平台实现的功能。比如 Windows 的注册表,这是 Windows 独有的东西,Java 并没有现成可以操作它的 API。
也有一些原因是非 Java 语言编写的代码已经经过了大量的测试,无需重新用 Java 实现一套。
当然,最初也有 JVM 运行的比较慢的原因,但随着 JVM 的不断发展,Java编写的代码有时已经不逊于一些 C/C++ 的代码了。
JNI 有着上述的一些好处,随着而来的是它会带来相应语言的缺点,
比如会引入 C 语言的无效指针造成的内存覆写问题等等。
所以说 JNI 实际上使用范围相对较窄,Web 后端方面用的比较少,安卓端用的相对更多一点。
示例 Hello World以下为一个简单的示例
Java 部分首先在在 Java 中声明 dll/so 库中定义的函数。
声明通过 native 关键字标识,提醒编译器该方法在外部定义。
// 为了简单,此处没有package public class HelloNative { public static native void greeting(); }C 部分
然后在 C 中定义函数,函数名有如下要求:
Java_包名_类名_方法名 。(其中的.号都要改为 _下划线)
如果类名中含有非 ASCII 码值,或说大于 uoo7F 的 Unicode 字符,用 _0xxxx 来代替。
(xxxx 是该字符的Unicode值的4个十六进制数序列)
方法重载需要在名称后加两个下划线,后再加上已编码的类型。
为了避免在函数定义时候出错,Java 提供了 javah 工具完成函数名的编写操作。
javah 是通过类文件来生成相应的文件的,所以源代码必须要先编译才可以。
javah HelloNative
通过如上命令,会生成一个 HelloNative.h 的文件,这个文件包含了 greeting() 方法的声明。
复制该文件,改为 .c 文件,去掉一些不需要的东西,然后包含 #include "HelloNative.h" 即可。
然后将方法声明改为方法实现,在方法实现中编写具体的代码。
JNIEXPORT void JNICALL Java_HelloNative_greeting (JNIEnv* env, jclass cl) { printf("Hello Native World!"); }
之后就是编译代码了,此处仅粘贴个人测试过的命令,为 Windows 上的 MinGW64 上的 gcc 。
gcc -I "jdk/include" -I "jdk/include/win32" -D __int64="long long" -shared -o HelloNative.dll HelloNative.c
关于 -D __int64="long long" 参数的说明:
Windows 上的 jni_md.h 含有声明 typedef __int64 jlong; ,它专用于 cl 的。如果使用 gcc 需要设置 -D __int64="long long"
或者也可以修改此文件,如:
#ifdef __GNUC__ typedef long long jlong; #else typedef __int64 jlong; #endif调用
创建 HelloNativeTest 类以供测试:
public class HelloNativeTest { static { // 此处不需要 dll/so 后缀,系统会自动根据系统不同换后缀 System.loadLibrary("HelloNative"); } public static void main(String[] args){ HelloNative.greeting(); } }
记住这里打印的消息是通过 printf 打印的,不是 java 的代码打印的。
注:
一些本地代码的共享库必须先运行初始化代码,可以将初始化代码放置到JNI_OnLoad方法中,如果提供该方法,则虚拟机关
闭时会调用JNI_OnUnload方法,原型如下:
jint JNI_OnLoad(JavaVM* vm, void* reserved); //返回它所需的虚拟机的最低版本,如JNI_VERSION_1_2 void JNI_OnUnload(JavaVM* vm, void* reserved);
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72634.html
摘要:介绍了在中配置的开发环境开发环境配置,开发环境配置完成之后,就要写一下著名的程序了。尤其是但是并不妨碍你使用其他语言,只要调用约定支持就可以了。是指定所在的目录,项目成功之后,会在目录里生成文件。是包名加上类名。 介绍了在Android Studio中配置NDK的开发环境:Android Studio NDK开发-环境配置,NDK开发环境配置完成之后,就要写一下著名的Hello Wor...
阅读 688·2021-11-22 13:54
阅读 3032·2021-09-26 10:16
阅读 3461·2021-09-08 09:35
阅读 1556·2019-08-30 15:55
阅读 3396·2019-08-30 15:54
阅读 2044·2019-08-30 10:57
阅读 456·2019-08-29 16:25
阅读 859·2019-08-29 16:15