知识大全 如何在Linux平台下使用JNI提高Java效率
Posted
知
篇首语:知识是头上的花环,而财产是颈上的枷锁。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 如何在Linux平台下使用JNI提高Java效率相关的知识,希望对你有一定的参考价值。
如何在Linux平台下使用JNI提高Java效率 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
Java的出现给大家开发带来的极大的方便 但是 如果我们有大量原有的经过广泛测试的非Java代码 将它们全部用Java来重写 恐怕会带来巨大的工作量和长期的测试 如果我们的应用中需要访问到特定的设备 甚至是仅符合公司内部信息交互规范的设备 或某个特定的操作系统才有的特性 Java就显得有些力不从心了 面对这些问题 Sun公司在JDK 中就定义了JNI规范 它规定了Java应用程序对本地方法的调用规则 实现步骤及相关函数使用 本文将一步步说明在Linux平台下如何实现本地共享库与Java协同工作 Hello World程序是目前标准的入门第一步 那么 我也以类似的应用最为样例 第一步 定义一个 Java 类 Hello 它提供SayHello方法 此时应注意两点 为要使用的每个本地方法编写本地方法声明 其声明方式与普通Java方法接口没什么不同 只是必须指定 native 关键字 如下所示 public native void SayHello(String strName); 在这个函数中 我们将根据传进的人名 向某人问好 必须显式地加载本地代码库 我们需在类的一个静态块中加载这个库 static System loadLibrary( hello ); 再加上必要的异常处理就生成如下源文件Hello java public class Hello static try //此处即为本地方法所在链接库名 System loadLibrary( hello ); catch(UnsatisfiedLinkError e) System err println ( Cannot load hello library:\\n + e toString() ); public Hello() //声明的本地方法 public native void SayHello(String strName); 编译后生成Hello class文件 第二步 生成本地链接库 具体过程如下 要为以上定义的类生成 Java 本地接口头文件 需使用javah Java 编译器的 javah 功能将根据Hello类生成必要的声明 此命令将生成Hello h文件 我们在共享库的代码中要包含它 javah不使默认内部命令 需要指明路径 它在JDK的bin目录下 在我的Linux环境下命令如下 /home/jbuilder/jdk /bin/javah Hello 生成的Hello h 文件 内容如下所示 /* DO NOT EDIT THIS FILE it is machine generated */ #include /* Header for class Hello */ #ifndef _Included_Hello #define _Included_Hello #ifdef __cplusplus extern C #endif /* * Class: Hello * Method: SayHello * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_Hello_SayHello (JNIEnv * jobject jstring); #ifdef __cplusplus #endif #endif 在与Hello h相同的路径下创建一个CPP文件Hello cpp 内容如下 #include Hello h #include //与Hello h中函数声明相同 JNIEXPORT void JNICALL Java_Hello_SayHello (JNIEnv * env jobject arg jstring instring) //从instring字符串取得指向字符串UTF编码的指针 const jbyte *str = (const jbyte *)env >GetStringUTFChars ( instring JNI_FALSE ); printf( Hello %s\\n str); //通知虚拟机本地代码不再需要通过str访问Java字符串 env >ReleaseStringUTFChars ( instring (const char *)str ); return; 所有的JNI调用都使用了JNIEnv*类型的指针 习惯上在CPP文件中将这个变量定义为evn 它是任意一个本地方法的第一个参数 env指针指向一个函数指针表 在VC中可以直接用 > 操作符访问其中的函数 jobject 指向在此 Java 代码中实例化的 Java 对象 LocalFunction的一个句柄 相当于this指针 后续的参数就是本地调用中有Java程序传进的参数 本例中只有一个String型参数 对于字符串型参数 因为在本地代码中不能直接读取Java字符串 而必须将其转换为C/C++字符串或Unicode 以下是三个我们经常会用到的字符串类型处理的函数 > > 参数 array 数组对象 isCopy 如果进行拷贝 指向以JNI_TRUE填充的jboolean 否则指向以JNI_FALSE填充的jboolean 例如 jboolean * GetBooleanArrayElements(jbooleanArray array jboolean *isCopy) void ReleaseXxxArrayElements(xxxArray array xxx *elems jint mode) 通知虚拟机不再需要从GetXxxArrayElements得到的指针 参数 array 数组对象 elems 不再需要的指向数组元素的指针 mode =在更新数组元素后释放elems缓冲器 JNI_MIT=在更新数组元素后不释放elems缓冲器 JNI_ABORT=不更新数组元素释放elems缓冲器 例如 void ReleaseBooleanArrayElements(jbooleanArray array jboolean *elems jint mode) xxxArray NewXxxArray(jsize len) 产生一个新的数组 通常在反值类型为数组型时用到 参数 len 数组中元素的个数 例如 jbooleanArray NewBooleanArray(jsize len) 编译生成共享库 使用GCC时 必须通知编译器在何处查找此Java本地方法的支持文件 并且显式通知编译器生成位置无关的代码 在我的环境中按如下过程编译 gcc I/home/jbuilder/jdk /include I/home /jbuilder/jdk /include/linux fPIC c Hello c 生成Hello o gcc shared Wl soname libhello so o libhello so Hello o 生成libhello so 接下来将生成的共享库拷贝为标准文件名 cp libhello so libhello so 最后通知动态链接程序此共享文件的路径 export LD_LIBRARY_PATH=`pwd` :$LD_LIBRARY_PATH 编写一个简单的Java程序来测试我们的本地方法 将如下源码存为ToSay java import Hello; import java util *; public class ToSay public static void main(String argv[]) ToSay say = new ToSay(); public ToSay() Hello h = new Hello(); //调用本地方法向John问好 h SayHello( John ); 用javac编译ToSay java 生成ToSay class向执行普通Java程序一样使用java ToSay 我们会看到在屏幕上出现Hello John 到这里我们就将整个的本地调用编写过程大概浏览了一遍 应用中注意事项 .如果可以通过TCP/IP实现Java代码与本地C/C++代码的交互工作 那么最好不使用以上提到的JNI的方式 因为一次JNI调用非常耗时 大概要花 ~ 个毫秒 .在一个Applet应用中 不要使用JNI 因为在 applet 中可能引发安全异常 .将所有本地方法都封装在单个类中 这个类调用单个 DLL 对于每种目标操作系统 都可以用特定于适当平台的版本替换这个 DLL 这样就可以将本地代码的影响减至最小 并有助于将以后所需的移植问题包含在内 .本地方法要简单 尽量将生成的DLL 对任何第三方运行时 DLL 的依赖减到最小 使本地方法尽量独立 以将加载DLL 和应用程序所需的开销减到最小 如果必须要运行时 DLL 则应随应用程序一起提供它们 .本地代码运行时 没有有效地防数组越界错误 错误指针引用带来的间接错误等 所以必须保证保证本地代码的稳定性 因为 丝毫的错误都可能导致Java虚拟机崩溃 结束语 JNI调用规范给我们复用原有其它语言的代码提供了简单易用的接口 可以节省大量的财力 使我们可以在享受Java带来的开发速度的同时 不必放弃旧有资源 const char* GetStringUTFChars (jstring string jboolean* isCopy) 返回指向字符串UTF编码的指针 如果不能创建这个字符数组 返回null 这个指针在调用ReleaseStringUTFChar()函数之前一直有效 参数 string Java字符串对象 isCopy 如果进行拷贝 指向以JNI_TRUE填充的jboolean 否则指向以JNI_FALSE填充的jboolean void ReleaseStringUTFChars(jstring str const char* chars) 通知虚拟机本地代码不再需要通过chars访问Java字符串 参数 string Java字符串对象 chars 由GetStringChars返回的指针 jstring NewStringUTF(const char *utf) 返回一个新的Java字符串并将utf内容拷贝入新串 如果不能创建字符串对象 返回null 通常在反值类型为string型时用到 参数 utf UTF编码的字符 cha138/Article/program/Java/JSP/201311/19137 相关参考
知识大全 Java通过JNI与Delphi交互
Java进阶:Java通过JNI与Delphi交互 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
知识大全 用JNI实现一个高精度的Java计时器
用JNI实现一个高精度的Java计时器 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &
知识大全 教您如何在Linux下配置Java开发环境详述
教您如何在Linux下配置Java开发环境详述 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 去
知识大全 Linux下java的Swing/AWT程序乱码解决
Linux下java的Swing/AWT程序乱码解决 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
知识大全 Linux平台数据库大比拼(3)
Linux平台数据库大比拼(3) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 评估大量因素
知识大全 Linux平台数据库大比拼(1)
Linux平台数据库大比拼(1) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 当第一次有人建议
知识大全 Linux 平台上之 Multipath Routing 应用
Linux平台上之MultipathRouting应用 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧
知识大全 用NuSphere MySQL快速构建Linux网络平台
用NuSphereMySQL快速构建Linux网络平台 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧
《会计信息化发展规划(2021—2025年)》提出,通过数据标准、信息共享机制和信息交换平台等方面的基础建设,在安全可控的前提下,初步实现监管部门间( )数据的互通和共享,提升监管效率,形成监管合力。
会计改革与发展十四五规划题目:《会计信息化发展规划(2021—2025年)》提出,通过数据标准、信息共享机制和信息交换平台等方面的基础建设,在安全可控的前提下,初步实现监管部门间()数据的互通和共享,
知识大全 oracle常用目录结构
oracle常用目录结构 大多数情况下了解Oracle常用目录结构将大大提高数据库管理与维护的工作效率本文介绍了Oracleg的常用目录 关于Linux下Oralce的安装请参照 VmWar