简体   繁体   中英

JNI UnsatisfiedLinkError… signature discrepancy?

In eclipse, on 64-bit windows, I am trying to get a JNI example working including trying out two methods of handling an in/out int argument. The program runs and executes sayHello(), but terminates with the following exception for modIntPtr():

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.aaa.bbb.ccc.HelloJNI.modIntPtr(I[I)V at com.aaa.bbb.ccc.HelloJNI.modIntPtr(Native Method) at com.aaa.bbb.ccc.HelloJNI.main(HelloJNI.java:18)

I double checked the library, it does have modIntPtr within it. So I'm thinking it must be a signature problem? In the .cpp file, modIntPtr has a jint, jintArray, and returns a void. That's (I[I)V. In the .h file, the signature is (I[I)V. In HelloJNI.java, I'm calling it like this: new HelloJNI().modIntPtr(100, intptr); intptr is type int[]. So that is (I[I)V as well.

So if the .dll contains the modIntPtr method, I'm sure it is up to date, I'm sure the program is linking with the correct .dll, and it's not a signature problem, what else could it be?

BTW, if I comment out the call to modIntPtr, modIntRef does work.

Thanks for any help!

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);
    }
 }

HelloJNI.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;
}

HelloJNI.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

And I'll include this file as well for anyone who is trying to find ideas for passing an in/out or mutable int parameter in java... I searched everywhere for a working example.
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;
    }
}

The code as posted runs without problems. I would try doing a clean build of the DLL; the JVM must be loading a stale version from somewhere.

By the way, there seems to be a bug in Java_com_aaa_bbb_ccc_HelloJNI_modIntPtr :

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

probably should be:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM