Java JNI介绍及JNI在Domino中的使用
来源:互联网 发布:光翼学园网络班有用吗 编辑:程序博客网 时间:2024/06/09 18:04
JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。
只有在必须的情况下才使用JNI,如下三种情况可作为参考:
1. 你的应用需要访问系统的各个特性和设备,这些特性和设备通过Java平台是无法访问的。
2. 你已经有了大量的测试过和调试过的用另一种语言编写的代码,并且知道如何将其导出到所有的目标平台上。
3. 通过基准测试,你已经发现所编写的Java代码比其他语言编写的等价代码要慢的多。
使用Java JNI需要如下步骤:
1. 编写Java类,以简单的输出“Hello Native World”为例子
/** * Native例子 * * @author weijielu */public class HelloNative { /** * native表示此方法是个本地方法,提醒编译器该方法将在外部 */ public static native void greeting();}
2. 编写一个相应的C函数(其实不需要手动编写,用javah程序即可自动生成)
2.1 首先编译HelloNative.java,用命令"javac HelloNative.java"
2.2 执行命令“jjavah -classpath C:\dde_root\90_ws\javaAPI\bin nativetest.HelloNative形成相应的C头文件(javah可以在jdk/bin目录下找到)
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class nativetest_HelloNative */#ifndef _Included_nativetest_HelloNative#define _Included_nativetest_HelloNative#ifdef __cplusplusextern "C" {#endif/* * Class: nativetest_HelloNative * Method: greeting * Signature: ()V */JNIEXPORT void JNICALL Java_nativetest_HelloNative_greeting (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif
3. 用C或者C++实现该本地方法
如果使用C++实现本地方法,必须将实现本地方法的函数声明为 extern "C",以阻止C++编译器生成C++特有的代码
#include "HelloNative.h"#include <stdio.h>JNIEXPORT void JNICALL Java_nativetest_HelloNative_greeting(JNIEnv* env, jclass cl){ printf("Hello Native World!\n");}
4. 编译本地代码并将其置于共享库中
5. 修改Java程序加载该类库
package nativetest;/** * Native例子 * * @author weijielu */public class HelloNative { static{ System.loadLibrary("HelloNative"); } /** * native表示此方法是个本地方法,提醒编译器该方法将在外部 */ public static native void greeting();}
6. 执行Java程序即可看到本地代码输出的东东了。
总结流程图:
下面就是我们下图中,红色椭圆形中的使用JNI的介绍了
众所周知我们Domino使用C/C++实现的,其对外提供的C/C++接口已经十分成熟,且执行效率很高。考虑到上述第2和第3条,对外提供Java API必然使用JNI。
以Java API中类lotus.domino.Database的remove方法为例介绍代码
1. 编写lotus.domino.Database类,类中有remove方法
package lotus.domino.local;public class Database extends NotesBaseimplements lotus.domino.Database{private native void Nremove(); // native表明这是本地方法public void remove()throws NotesException{synchronized(this){this.CheckObject();Nremove();markInvalid();}}}
2. 本地andb.hpp文件(奇怪,在相应的hpp文件里没有相应的Nremove)
3. 本地andb.cpp文件 (贱人起得这个难找难记的文件名字)
JNIEXPORT void JNICALL Java_lotus_notes_Database_Nremove (JNIEnv *env, jobject jthis){Java_lotus_domino_local_Database_Nremove(env, jthis);}JNIEXPORT void JNICALL Java_lotus_domino_local_Database_Nremove (JNIEnv *env, jobject jthis){lptr(ANDatabase) db;JAVA_WRITE_BLOCK_BEGIN(jthis)LSMSG_PARAM objptr = ANotes::ANExtractPointer(env, jthis);if (objptr){ JAVA_PROFILE_METHOD(mysession, objptr, CNOTES_DBMETH_REMOVE);db = (lptr(ANDatabase))objptr;db->ANDDeleteDb(NULL); JAVA_PROFILE_END}JAVA_BLOCK_END;}
4. 类库的加载我们有一套机制,在此不再赘余
5. 在此我们即可在Java中使用lotus.domino.local.Database类中的 remove()方法了。
多说两句:Domino对外提供Java API使用JNI有一个JNI的共通的问题,即C/C++代码有内存泄露的风险,当Java API使用完一个Domino Java类的时候必须主动告诉C/C++进行对象的内存释放,即调用Java中的recycle()方法。由于Java中的对象是不需要主动回收的,Java虚拟机会进行回收,所有Java程序员使用Domino Java API很容易忘记最后调用recycle()方法。我们的REST Service中的调用Java API的一块代码就是因为忘记recycle导致在性能测试的时候使得内存耗尽而使Domino 崩溃。典型的调用recycle()方法如下:
protected boolean formInDB(String extFileName) throws NotesException {boolean bFound = false;Database dbTr = null;DocumentCollection dc = null;try{dbTr = getPrimaryServiceManager().getDatabase(TRDB);if(Verify.notNull("There should be " + TRDB + " on Server: " + getPrimaryServiceManager().fqih, dbTr)){String sQuery = "FORM = \"ExtensionFiles\" & extensionFileName = \"" + extFileName + "\"";dc = dbTr.search(sQuery);bFound = !(dc.getCount() == 0);}else{bFound = false;}}catch(NotesException e){log("ERROR: Problems occur when search document in tr.nsf");e.printStackTrace();}finally{if(dc != null){dc.recycle();}if(dbTr != null){dbTr.recycle();}}return bFound;}
- Java JNI介绍及JNI在Domino中的使用
- Java JNI介绍及JNI在Domino中的使用
- JNI介绍及视频教程
- JAVA JNI介绍
- Java JNI介绍
- Java JNI 详细介绍
- java native方法使用及JNI实例
- 在纯java中使用JNI
- 在java中使用JNI来编程
- jni数据类型及使用
- jni使用中的问题
- JAVA中的JNI
- Java中的JNI调用
- Java -- JNI中的数据类型
- JNI介绍及简单实例
- Cygwin的安装及在Android jni中的简单使用举例
- JAVA JNI 使用实例
- JAVA JNI 使用实例
- 【头发重建重要进展】Disney Researchers develop method to capture stylized hair for 3D-printed figurines
- swt中的table单元格渐变颜色
- C++拷贝构造函数详解
- Oracle工具orachk使用说明
- 心累的时候,给自己放个假,给自己一个欣赏世界的理由。
- Java JNI介绍及JNI在Domino中的使用
- YII读书笔记
- 将django部署到Apache服务器
- ios-ios 7之前和之后关于状态栏隐藏的介绍
- 13. 枚举
- NDK Application.mk使用手册
- 子序列和最大问题
- c++中sort()及qsort()的用法总结
- c++ const char* to const void