JAVA之JNI原理、開發步驟及示列

JNI介紹及原理

    JVM封裝了各類操做系統實際的差別性的同時,提供了jni技術,使得開發者能夠經過java程序(代碼)調用到操做系統相關的技術實現的庫函數,從而與其餘技術和系統交互,使用其餘技術實現的系統的功能;同時其餘技術和系統也能夠經過jni提供的相應原生接口開調用java應用系統內部實現的功能。html

    在windows系統上,通常可執行的應用程序都是基於native的PE結構,windows上的jvm也是基於native結構實現的。Java應用體系都是構建於jvm之上。java

    有了JAVA標準平臺的支持,使JNI模式更加易於實現和使用android

JNI程序開發的通常操做步驟

  1. 編寫帶有native聲明的方法的java類
  2. 使用javac命令編譯所編寫的java類
  3. 而後使用javah + java類名生成擴展名爲h的頭文件
  4. 使用C/C++實現本地方法
  5. 將C/C++編寫的文件生成動態鏈接庫

簡單示例

    ltp4j不支持使用個性化分詞模型,須要經過JNI的方式增長此功能ios

定義JAVA調用類接口

package edu.hit.ir.ltp4j;
import java.util.List;
public class CustomizedSegmentor
{
  static
  {
    System.loadLibrary("customized_segmentor_jni");
  }

  public static native int create(String paramString1, String paramString2);

  public static native int create(String paramString1, String paramString2, String paramString3);

  public static native int segment(String paramString, List<String> paramList);

  public static native void release();
}

編譯JAVA類

    javac edu/hit/ir/ltp4j/CustomizedSegmentor.javac++

產生c/c++原生函數的頭文件

     javah -jni edu.hit.ir.ltp4j.CustomizedSegmentorgit

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class edu_hit_ir_ltp4j_CustomizedSegmentor */

#ifndef _Included_edu_hit_ir_ltp4j_CustomizedSegmentor
#define _Included_edu_hit_ir_ltp4j_CustomizedSegmentor
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     edu_hit_ir_ltp4j_CustomizedSegmentor
 * Method:    create
 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_create__Ljava_lang_String_2Ljava_lang_String_2
  (JNIEnv *, jclass, jstring, jstring);

/*
 * Class:     edu_hit_ir_ltp4j_CustomizedSegmentor
 * Method:    create
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_create__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2
  (JNIEnv *, jclass, jstring, jstring, jstring);

/*
 * Class:     edu_hit_ir_ltp4j_CustomizedSegmentor
 * Method:    segment
 * Signature: (Ljava/lang/String;Ljava/util/List;)I
 */
JNIEXPORT jint JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_segment
  (JNIEnv *, jclass, jstring, jobject);

/*
 * Class:     edu_hit_ir_ltp4j_CustomizedSegmentor
 * Method:    release
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_release
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

編寫cpp文件

    直接調用segment_dll.h裏的函數  參考:https://github.com/HIT-SCIR/ltp/blob/master/src/segmentor/segment_dll.hhttps://github.com/HIT-SCIR/ltp4j/blob/master/jni/edu_hit_ir_ltp4j_Segmentor.hhttps://github.com/HIT-SCIR/ltp4j/blob/master/jni/segment_jni.cppgithub

// segmentor_jni.cpp : Defines the exported functions for the DLL application.
//

#include "ltp/segment_dll.h"
#include "edu_hit_ir_ltp4j_CustomizedSegmentor.h"
#include "string_to_jstring.hpp"
#include <iostream>
#include <string>
#include <vector>

using namespace std;

static void * segmentor = NULL;

JNIEXPORT jint JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_create__Ljava_lang_String_2Ljava_lang_String_2
(JNIEnv * env, jclass obj, jstring model_path1, jstring model_path2){
  const char * str_model1 = env->GetStringUTFChars( model_path1 , 0);
  const char * str_model2 = env->GetStringUTFChars( model_path2 , 0);
  if(!segmentor){
    segmentor = customized_segmentor_create_segmentor(str_model1,str_model2);
  }
  else{
    customized_segmentor_release_segmentor(segmentor);
    segmentor = customized_segmentor_create_segmentor(str_model1,str_model2);
  }
  env->ReleaseStringUTFChars( model_path1, str_model1); 
  env->ReleaseStringUTFChars( model_path2, str_model2); 
  if(segmentor) {
    return 1;
  }
  return -1;
}

JNIEXPORT jint JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_create__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2
(JNIEnv * env, jclass obj, jstring model_path1, jstring model_path2, jstring lexicon_path){
  const char * str_model1 = env->GetStringUTFChars( model_path1 , 0);
  const char * str_model2 = env->GetStringUTFChars( model_path2 , 0);
  const char * str_lexicon = env->GetStringUTFChars( lexicon_path , 0);
  if(!segmentor){
    segmentor = customized_segmentor_create_segmentor(str_model1,str_model2,str_lexicon);
  }
  else{
    customized_segmentor_release_segmentor(segmentor);
    segmentor = customized_segmentor_create_segmentor(str_model1,str_model2,str_lexicon);
  }
  env->ReleaseStringUTFChars( model_path1, str_model1); 
  env->ReleaseStringUTFChars( model_path2, str_model2); 
  env->ReleaseStringUTFChars( lexicon_path, str_lexicon); 
  if(segmentor) {
    return 1;
  }
  return -1;
}

JNIEXPORT jint JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_segment
(JNIEnv * env, jclass obj, jstring sent, jobject array_words){
  jclass array_list = env->GetObjectClass(array_words);

  jmethodID list_add = env->GetMethodID(array_list,"add","(Ljava/lang/Object;)Z");

  const char * str_sent = env->GetStringUTFChars( sent , 0);
  std::string sentence(str_sent);
  std::vector<std::string> words;

  int len = customized_segmentor_segment(segmentor,sentence,words);
  for(int i = 0;i<len;i++){
    jobject tmp = stringToJstring(env,words[i].c_str());
    env->CallBooleanMethod(array_words,list_add,tmp);
  }
  env->ReleaseStringUTFChars(sent, str_sent); 
  return len;
}

JNIEXPORT void JNICALL Java_edu_hit_ir_ltp4j_CustomizedSegmentor_release
(JNIEnv * env, jclass obj){
  customized_segmentor_release_segmentor(segmentor);
  segmentor = NULL;
}

編譯,產生so文件

    vi CMakeLists.txt  在文件中添加以下內容:windows

    add_library (customized_segmentor_jni SHARED ${JNI_SOURCE_DIR}/customized_segment_jni.cpp)app

target_link_libraries (customized_segmentor_jni segmentor)jvm

採用cmake進行編譯

JAVA調用示例

static {
       if (CustomizedSegmentor.create("customized.model", "cws.model") < 0) {
       System.err.println("load failed");
       System.exit(1);
   }
}
List words = new ArrayList();
int size = CustomizedSegmentor.segment(line, words);
CustomizedSegmentor.release();

參考

http://baike.baidu.com/link?url=rthf0sbZ4t_EAojpchZ0D9tQmmoMVR672uyVBiXwR2huPdZK_YIR2n2Tc5hHp3oPddE_9Jn_yYtULHE8S-km__

http://www.iteye.com/topic/304594

http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html

相關文章
相關標籤/搜索