0

I get the following error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: model.JNIResultSet.getSpieler()[Lmodel/Spieler;
    at model.JNIResultSet.getSpieler(Native Method)
    at model.JNIResultSet.main(JNIResultSet.java:18)

My java classes look like this:

package model;

public class Spieler {
private String vorname;
private String nachname;
private int trikotnummer;


public Spieler(String vorname, String nachname, int trikotnummer) {
    this.vorname = vorname;
    this.nachname = nachname;
    this.trikotnummer = trikotnummer;
}
}

and

package model;

public class JNIResultSet {

public JNIResultSet() { }

public native Spieler[] getSpieler();

static {
    System.loadLibrary("spieler");
}

public static void main(String[] args) {
    JNIResultSet jni = new JNIResultSet();
    Spieler s[] = jni.getSpieler();
    System.out.println("Laenge: " + s.length);
}


}

My header file looks like that:

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

#ifndef _Included_model_JNIResultSet
#define _Included_model_JNIResultSet
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     model_JNIResultSet
* Method:    getSpieler
* Signature: ()[Lmodel/Spieler;
*/
JNIEXPORT jobjectArray JNICALL Java_model_JNIResultSet_getSpieler
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

And finally my C code looks like that:

JNIEXPORT jobjectArray JNICALL
JAVA_model_JNIResultSet_getSpieler(JNIEnv *env, jobject obj) {

Spieler *ptr = head;
jobjectArray ret;
int i;
jclass clazz = (*env)->FindClass(env, "model/Spieler");
jmethodID mid = (*env)->GetMethodID(env, clazz, "<init>", "(III)V");
jobject object; 

ret= (*env)->NewObjectArray(env, count,
        clazz,
        NULL);

for(i = 0; i < count; i++) {
    object = (*env)->NewObject(env, clazz, mid, ptr);
    (*env)->SetObjectArrayElement(env,
            ret, i, object);
    ptr = ptr->next;
}

return ret;
}

Do you have any suggestions how to fix that problem?
I also don't know if the C code is right, maybe that's the problem?

I execute it this way:

cd src
javac model/JNIResultSet.java
cd ..

cd bin
javah -jni model.JNIResultSet

gcc -fPIC -o libspieler.so -shared -I/usr/java/jdk1.8.0_73/include/ SharedTable.c -lc

java -Djava.library.path=/home/pupil/workspace/JNITableV2/bin/ model.JNIResultSet

Probably this is the error I've updated the C code but I think it's wrong:

jclass clazz = (*env)->FindClass(env, "model/JNIResultSet");
jmethodID mid = (*env)->GetMethodID(env, clazz, "getSpieler", "()Lmodel/Spieler;");

nm -D reports:

U atoi
0000000000202088 B bss_start
00000000002020b0 B current
w __cxa_finalize
0000000000202088 D _edata
00000000002022b8 B _end
U fclose
0000000000000ef0 T _fini
U fopen
w __gmon_start

00000000002020a8 B head
0000000000000948 T _init
0000000000000b35 T insertFirst
U _IO_getc
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000000ca2 T JAVA_model_JNIResultSet_getSpieler
w _Jv_RegisterClasses
U malloc
U memcpy
U memset
0000000000000c49 T reverse
U strcpy
00000000002020c0 B string
U strlen

20
  • Does your .c file include the .h file? and does javap -s agree with the method signature you're using? and does javah agree with the current .h and .c files? Commented Oct 10, 2016 at 9:45
  • Yeah I included the .h file. And as you see the method in the .h file is the same as in the .c file.. Probably findClass or something else in the C code is the problem? Commented Oct 10, 2016 at 9:47
  • No, the linkage between the native Java method and the .c method is the problem. That's what the error message is telling you. Commented Oct 10, 2016 at 9:48
  • How can I include the Spieler class maybe that's the problem? Commented Oct 10, 2016 at 9:53
  • Include it in what? It's pure Java. As long as it's on the CLASSPATH it is available to JNI. Commented Oct 10, 2016 at 9:57

2 Answers 2

2

getSpieler() method could be declared static; you can use it without instantiating JNIResultSet class.

mid should point to the constructor, not getSpieler(), but the <init> signature is wrong: it should take Ljava/lang/String;Ljava/lang/String;I and not three ints:

jmethodID mid = (*env)->GetMethodID(env, clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;I)V");
…
jobject strVorname = (*env)->NewStringUTF(env, ptr->vorname);
jobject strNachname = (*env)->NewStringUTF(env, ptr->nachname);
object = (*env)->NewObject(env, clazz, mid, strVorname, strNachname, ptr->trikotnummer);

Always check the method IDs and objects for NULL before proceeding to the next step.

Regarding the unsatisfied link, check that the libspieler.so file is good: run nm -D to see if JAVA_model_JNIResultSet_getSpieler is actually exported. rename JAVA_model_JNIResultSet_getSpieler to Java_model_JNIResultSet_getSpieler, exactly as indicated in the generated .h file.

Sign up to request clarification or add additional context in comments.

8 Comments

And what could I write for the constructor instead of <init> ?
Where and how should I run nm -D? nm -D libspieler.so?
This guy has the same problem as me. How can I fix that in my example? stackoverflow.com/questions/4526198/…
Your C code uses the constructor of Java class, not the native method that it implements. Please see the edit - you also must give the parameters to the constructor!
What does your nm -D report?
|
-2

It's probably a issue of PATH or LD_LIBRARY_PATH variable (on linux, not sure whats the environment key on windows). Trying add the directories to these variable, export them and run the application.

Try it in new session.

2 Comments

No. If that was the problem the exception would have been thrown by loadLibrary(). The library has been loaded successfully, so the problem is clearly what is in the library: almost certainly a disagreement between the Java method signature and what is in the C code.
@mafioso Of course it's the C code. It isn't satisfying the JNI linkage required.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.