JNI java.lang.UnsatisfiedLinkError

使用VS2010编译JNI,开始时Java端调用正常,加入几个函数后,怎么都无法调用了,报如下错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.mingspy.jseg.JSegJNI.MaxSplit(Ljava/lang/String;)Ljava/util/List;

在网上查询了一下,可能是jni端函数名字编译时,多了字符@,需要加参数。查询了不少文章,只是用于gcc的(如加入在linker flags处填入:-Wl,--add-stdcall-alias),唯独没有关于VS的。

最后采用RegisterNativeMethods解决。摘自网上的一段评论如下:

除了使用传统方法实现JNI外,也可以使用RegisterNatives实现JNI。和传统方法相比,使用RegisterNatives的好处有三点:
1、C++中函数命名自由,不必像javah自动生成的函数声明那样,拘泥特定的命名方式;
2、效率高。传统方式下,Java类call本地函数时,通常是依靠VM去动态寻找.so中的本地函数(因此它们才需要特定规则的命名格式),而使用RegisterNatives将本地函数向VM进行登记,可以让其更有效率的找到函数;
3、运行时动态调整本地函数与Java函数值之间的映射关系,只需要多次call RegisterNatives()方法,并传入不同的映射表参数即可。
为了使用RegisterNatives,我们需要了解JNI_OnLoad和JNI_OnUnload函数。JNI_OnLoad()函数在VM执行System.loadLibrary(xxx)函数时被调用,它有两个重要的作用:

  • 指定JNI版本:告诉VM该组件使用那一个JNI版本(若未提供 JNI_OnLoad()函数,VM会默认该使用最老的JNI 1.1版),如果要使用新版本的JNI,例如JNI 1.4版,则必须由JNI_OnLoad()函数返回常量JNI_VERSION_1_4(该常量定义在jni.h中) 来告知VM。
  • 初始化设定,当VM执行到System.loadLibrary()函数时,会立即先呼叫JNI_OnLoad()方法,因此在该方法中进行各种资源的初始化操作最为恰当,RegisterNatives也在这里进行。

JNI_OnUnload()当VM释放该组件时被调用,JNI_OnUnload()函数的作用与JNI_OnLoad()对应,因此在该方法中进行善后清理,资源释放的动作最为合适。


我的代码示例如下, 见JNI_OnLoad


#include 
//#include "JSegJNI.h"
#include 
#include "AutoTokenizer.hpp"
#include "CodeUtils.hpp"
using namespace std;
using namespace mingspy;
 
static ITokenizer & GetTokenizer(){
    static AutoTokenizer t;
    return t;
}
static jobject toJavaList(JNIEnv * env, const vector & result){
    jclass list_cls = env->FindClass("Ljava/util/ArrayList;");//获得ArrayList类引用
    jmethodID list_costruct = env->GetMethodID(list_cls , "","()V"); //获得得构造函数Id
    jmethodID list_add = env->GetMethodID(list_cls,"add","(Ljava/lang/Object;)Z");
    jobject list_obj = env->NewObject(list_cls , list_costruct);
    jclass token_cls = env->FindClass("Lcom/mingspy/jseg/Token;");
    jmethodID token_costruct = env->GetMethodID(token_cls , "", "(II)V");
    for(int i = 0 ; i < result.size(); i++)
    {
        jobject t_obj = env->NewObject(token_cls , token_costruct , result[i]._off,result[i]._len);
        env->CallBooleanMethod(list_obj , list_add , t_obj);
    }
    return list_obj ;
}
/*
 * Class: com_mingspy_jseg_JSegJNI
 * Method: MaxSplit
 * Signature: (Ljava/lang/String;)Ljava/util/List;
 */
jobject Java_com_mingspy_jseg_JSegJNI_MaxSplit
  (JNIEnv * env, jobject obj, jstring jstr)
{
    const char * p = env->GetStringUTFChars(jstr, 0);
    vector result;
    GetTokenizer().maxSplit(Utf8ToUnicode(p), result);
    env->ReleaseStringUTFChars(jstr, p);
    return toJavaList(env,result);
}
/*
 * Class: com_mingspy_jseg_JSegJNI
 * Method: FullSplit
 * Signature: (Ljava/lang/String;)Ljava/util/List;
 */
jobject Java_com_mingspy_jseg_JSegJNI_FullSplit
  (JNIEnv * env, jobject obj, jstring jstr)
{
    const char * p = env->GetStringUTFChars(jstr, 0);
    vector result;
    GetTokenizer().fullSplit(Utf8ToUnicode(p), result);
    env->ReleaseStringUTFChars(jstr, p);
    return toJavaList(env,result);
}
/*
 * Class: com_mingspy_jseg_JSegJNI
 * Method: UniGramSplit
 * Signature: (Ljava/lang/String;)Ljava/util/List;
 */
jobject Java_com_mingspy_jseg_JSegJNI_UniGramSplit
 (JNIEnv * env, jobject obj, jstring jstr){
      const char * p = env->GetStringUTFChars(jstr, 0);
      vector result;
      GetTokenizer().uniGramSplit(Utf8ToUnicode(p), result);
      env->ReleaseStringUTFChars(jstr, p);
      return toJavaList(env,result);
}
/*
 * Class: com_mingspy_jseg_JSegJNI
 * Method: BiGramSplit
 * Signature: (Ljava/lang/String;)Ljava/util/List;
 */
jobject Java_com_mingspy_jseg_JSegJNI_BiGramSplit
 (JNIEnv * env, jobject obj, jstring jstr){
        const char * p = env->GetStringUTFChars(jstr, 0);
        vector result;
        GetTokenizer().biGramSplit(Utf8ToUnicode(p), result);
        env->ReleaseStringUTFChars(jstr, p);
        return toJavaList(env,result);
}
/*
 * Class: com_mingspy_jseg_JSegJNI
 * Method: MixSplit
 * Signature: (Ljava/lang/String;)Ljava/util/List;
 */
jobject Java_com_mingspy_jseg_JSegJNI_MixSplit
(JNIEnv * env, jobject obj, jstring jstr)
{
        const char * p = env->GetStringUTFChars(jstr, 0);
        vector result;
        GetTokenizer().mixSplit(Utf8ToUnicode(p), result);
        env->ReleaseStringUTFChars(jstr, p);
        return toJavaList(env,result);
}
/*
 * Class: com_mingspy_jseg_JSegJNI
 * Method: Test
 * Signature: (Ljava/lang/String;)V
 */
void Java_com_mingspy_jseg_JSegJNI_Test
  (JNIEnv * env, jobject obj, jstring jstr)
{
    const char * p = env->GetStringUTFChars(jstr, 0);
    cout<<"input is:"< result;
    GetTokenizer().maxSplit(Utf8ToUnicode(p), result);
    env->ReleaseStringUTFChars(jstr, p);
    for(int i = 0; i< result.size(); i++){
        cout<<"("<GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
    {
        return JNI_ERR;
    }
    jclass cls = env->FindClass("Lcom/mingspy/jseg/JSegJNI;");
    if (cls == NULL)
    {
        return JNI_ERR;
    }
    int len = sizeof(s_methods) / sizeof(s_methods[0]);
    if (env->RegisterNatives(cls, s_methods, len) < 0)
    {
        return JNI_ERR;
    }
    return JNI_VERSION_1_4;
}



你可能感兴趣的:(C/C++,java)