java - JNI UnsatisfiedLinkError ...签名不一致?

标签 java c++ eclipse java-native-interface

在 64 位 Windows 上的 eclipse 中,我试图让 JNI 示例正常工作,包括尝试两种处理 in/out int 参数的方法。程序运行并执行 sayHello(),但终止并出现以下 modIntPtr() 异常:

线程“main”中的异常 java.lang.UnsatisfiedLinkError: com.aaa.bbb.ccc.HelloJNI.modIntPtr(I[I)V 在 com.aaa.bbb.ccc.HelloJNI.modIntPtr( native 方法) 在 com.aaa.bbb.ccc.HelloJNI.main(HelloJNI.java:18)

我仔细检查了这个库,里面确实有 modIntPtr。所以我认为这一定是签名问题?在.cpp文件中,modIntPtr有一个jint,jintArray,返回一个void。那是 (I[I)V。在 .h 文件中,签名是 (I[I)V。在 HelloJNI.java 中,我这样调用它: 新的 HelloJNI().modIntPtr(100, intptr); intptr 是 int[] 类型。所以这也是 (I[I)V]。

因此,如果 .dll 包含 modIntPtr 方法,我确定它是最新的,我确定该程序正在与正确的 .dll 链接,并且这不是签名问题,还有什么可能?

顺便说一句,如果我注释掉对 modIntPtr 的调用,modIntRef 确实有效。

感谢您的帮助!

HelloJNI.java:

package com.aaa.bbb.ccc;

public class HelloJNI {
    static {
       System.loadLibrary("com_aaa_bbb_ccc");
    }
    // A native method that receives nothing and returns void
    private native void sayHello();
    private native void modIntPtr(int delta, int[] intptr);
    private native void modIntRef(int delta, IntRef intref);

    public static void main(String[] args) {
       int[] intptr = new int[1];
       intptr[0]=42;
       IntRef intref = new IntRef(24);

       new HelloJNI().sayHello();  // invoke the native method
       new HelloJNI().modIntPtr(100, intptr);
       new HelloJNI().modIntRef(100, intref);
    }
 }

你好JNI.cpp

#include <jni.h>
#include <stdio.h>
#include "HelloJNI.h"

void SayHello(void)
{
   printf("Hello World!\n");
   return;
}

void IntRefNative(int delta, int *intptr)
{
   printf("delta  = %d\n",delta);
   printf("intptr = %d\n",*intptr);

   *intptr += delta;

   printf("After mod...\n");
   printf("intptr = %d\n",*intptr);

   return;
}


JNIEXPORT void JNICALL Java_com_aaa_bbb_ccc_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {
   SayHello();
   return;
} 

JNIEXPORT void JNICALL Java_com_aaa_bbb_ccc_HelloJNI_modIntPtr(JNIEnv *env, jobject thisObj, jint delta, jintArray intptr) {
   jint *body = env->GetIntArrayElements(intptr, 0);
   printf("delta  = %d\n",delta);
   printf("intptr = %d\n",intptr[0]);

   body[0] += delta;
   env->ReleaseIntArrayElements(intptr, body, 0);

   printf("After mod...\n");
   printf("intptr = %d\n",intptr[0]);
   return;
} 

JNIEXPORT void JNICALL Java_com_aaa_bbb_ccc_HelloJNI_modIntRef(JNIEnv *env, jobject thisObj, jint delta, jobject intref) {
    jclass cls = env->GetObjectClass(intref);

    jmethodID methodID = env->GetMethodID(cls, "getValue", "()I");   
    jint value = env->CallIntMethod(intref, methodID);   
    IntRefNative(delta, (int *)(&value));   
    methodID = env->GetMethodID(cls, "setValue", "(I)V");   
    env->CallVoidMethod(intref, methodID, value);   

   return;
}

你好JNI.h

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

#ifndef _Included_com_aaa_bbb_ccc_HelloJNI
#define _Included_com_aaa_bbb_ccc_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_aaa_bbb_ccc_HelloJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_aaa_bbb_ccc_HelloJNI_sayHello
  (JNIEnv *, jobject);

/*
 * Class:     com_aaa_bbb_ccc_HelloJNI
 * Method:    modIntPtr
 * Signature: (I[I)V
 */
JNIEXPORT void JNICALL Java_com_aaa_bbb_ccc_HelloJNI_modIntPtr
  (JNIEnv *, jobject, jint, jintArray);

/*
 * Class:     com_aaa_bbb_ccc_HelloJNI
 * Method:    modIntRef
 * Signature: (ILcom/aaa/bbb/ccc/IntRef;)V
 */
JNIEXPORT void JNICALL Java_com_aaa_bbb_ccc_HelloJNI_modIntRef
  (JNIEnv *, jobject, jint, jobject);

#ifdef __cplusplus
}
#endif
#endif

对于任何试图寻找在 java 中传递输入/输出或可变 int 参数的想法的人,我也会包括这个文件...我到处搜索了一个工作示例。
IntRef.java

package com.aaa.bbb.ccc;

public class IntRef {

    private int value;

    IntRef() {
        value=0;
    }

    IntRef(int v) {
        value = v;
    }

    /**
     * Returns the integer value of this <code>IntRef</code>
     *
     * @return the value of the integer in native int form
     */
    public int getValue() {
        return value;
    }

    /**
     * Sets the value.
     *
     * @param theValue The value to set
     */
    public void setValue(int theValue) {
        this.value = theValue;
    }
}

最佳答案

发布的代码运行没有问题。我会尝试做一个干净的 DLL 构建; JVM 必须从某处加载过时的版本。

顺便说一下,Java_com_aaa_bbb_ccc_HelloJNI_modIntPtr 中似乎有一个错误:

printf("intptr = %d\n",intptr[0]);

可能应该是:

printf("intptr = %d\n",body[0]);

关于java - JNI UnsatisfiedLinkError ...签名不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16614844/

相关文章:

c++ - 假设类模板参数

c++ - 在 cmake 中使用 Pcap++ 库

eclipse - Eclipse 中的内容辅助不适用于 JSP 文件中的 EL

android - 从 phpmyadmin 获取数据并将每个项目传输到 eclipse 中的 TextView

java - 当我尝试将 Firebase 数据库中的项目包含在其项目列表中时,如何修复微调器不断关闭并重新打开的问题

java - 通过多词搜索键搜索存储在 arraylist 中的对象

java - 如何在继续之前检查一组变量是否不为空

java - 原始类型导致的代码重复 : How to avoid insanity?

c++ - 如何使用纯 C++ 或 winapi 计算给定目录中的项目数?

java - 在 tabris 中创建应用程序