JAVA之JNI原理、开发步骤及示列

JNI介绍及原理

    JVM封装了各种操作系统实际的差异性的同时,提供了jni技术,使得开发者可以通过java程序(代码)调用到操作系统相关的技术实现的库函数,从而与其他技术和系统交互,使用其他技术实现的系统的功能;同时其他技术和系统也可以通过jni提供的相应原生接口开调用java应用系统内部实现的功能。

    在windows系统上,一般可执行的应用程序都是基于native的PE结构,windows上的jvm也是基于native结构实现的。Java应用体系都是构建于jvm之上。

    有了JAVA标准平台的支持,使JNI模式更加易于实现和使用

24114539_QIAR.png

JNI程序开发的一般操作步骤

  1. 编写带有native声明的方法的java类
  2. 使用javac命令编译所编写的java类
  3. 然后使用javah + java类名生成扩展名为h的头文件
  4. 使用C/C++实现本地方法
  5. 将C/C++编写的文件生成动态连接库

简单示例

    ltp4j不支持使用个性化分词模型,需要通过JNI的方式增加此功能

定义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.java

产生c/c++原生函数的头文件

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

/* 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.cpp

// 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  在文件中添加如下内容:

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

target_link_libraries (customized_segmentor_jni segmentor)

采用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

转载于:https://my.oschina.net/cloudcoder/blog/700312

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值