JNI: библиотека найдена по пути, а метод - нет (java.lang.UnsatisfiedLinkError) - PullRequest
6 голосов
/ 21 февраля 2012

Я пытаюсь использовать JNI и получаю java.lang.UnsatisfiedLinkError.В отличие от других миллионов вопросов, задаваемых по этому поводу, у меня есть библиотека на моем пути, и я даже видел, как исключение изменилось, когда я удаляю его.Я уверен, что что-то не так с DLL, которую я создал, но я не уверен, что.

Вот мой код класса Java:

package com;

public class Tune {
    static {
        System.loadLibrary("lala");
    }
    public static void main(String[] args) {
        Tune j = new Tune();
        System.out.println("2+6="+j.add(2, 6));
    }
    native public int add(int x,int y);
}

Вот сокращенная частьмоего заголовочного файла, созданного javah:

/*
 * Class:     com_Tune
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv *, jobject, jint, jint);

Вот мой код на C ++:

#include <jni.h>
#include <com_Tune.h>

JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv * env, jobject obj, jint x, jint y) {
    return x+y;
  }

Вот исключение времени выполнения, которое я получаю из eclipse:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.Tune.add(II)I
    at com.Tune.add(Native Method)
    at com.Tune.main(Tune.java:9)

Я прочитал, что вышеупомянутое исключение означает, что он нашел библиотеку "lala", но метод "add" все еще не определен.Единственное, что я вижу в своем проекте и в учебнике по-разному:

  • Мой использует пакет вместо пакета по умолчанию (разве учебники не должны этого делать?!?!)
    • У меня есть возвращаемое значение.
    • Я переместил свою dll после того, как она была создана (я не думаю, что это сломает ее, так как мой путь настроен.)

Как это возможно?

Другая информация:

ОС: Windows 7JDK: 1.6.0_31 (для x86, 32-битная jvm)C ++ IDE: Code :: Blocks (dll была автоматически скомпилирована IDE Code :: Blocks)Компилятор C ++: MinGW32-g ++ (компилятор GNU C ++)

У меня есть jni.h и com_Tune.h в C: \ _ \ includeУ меня есть lala.dll в C: \ _ \ lib

Переменные среды:ПУТЬ: C: \ Program Files (x86) \ NVIDIA Corporation \ PhysX \ Common;% CommonProgramFiles% \ Microsoft Shared \ Windows Live; C: \ Program Files (x86) \ AMD APP \ bin \ x86_64; C: \ Program Files (x86) \ AMD APP \ bin \ x86;% SystemRoot% \ system32;% SystemRoot%;% SystemRoot% \ System32 \ Wbem;% SYSTEMROOT% \ System32 \ WindowsPowerShell \ v1.0 \; C: \ Program Files (x86) \ATI Technologies \ ATI.ACE \ Core-Static; C: \ Apps;% JAVA_HOME% \ bin; C: \ Program Files \ MySQL \ MySQL Server 5.5 \ bin;% MAVEN_HOME% \ bin;% HADOOP_INSTALL% \ bin; c:\ Program Files (x86) \ Microsoft SQL Server \ 100 \ Tools \ Binn \; c: \ Program Files \ Microsoft SQL Server \ 100 \ Tools \ Binn \; c: \ Program Files \ Microsoft SQL Server \ 100 \ DTS \ Binn\; C: \ MinGW \ bin; C: \ Program Files (x86) \ GnuWin32 \ bin; C: _ \ path; C: \ _ \ lib; C: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ VC\ Bin; C: \ _ \ включают

Ответы [ 5 ]

4 голосов
/ 03 октября 2012

Проблема связана с именем, сгенерированным компилятором: Java_com_Tune_add@16

Использование любого из двух

gcc -Wl,-kill-at

Или

gcc -Wl,--add-stdcall-alias

Это обеспечит генерацию Java_com_Tune_add

И тогда ваш вызов метода будет успешным.

2 голосов
/ 21 февраля 2012

Одним из возможных источников проблемы может быть то, что вы скомпилировали код с использованием компилятора C ++, который использует [соглашение о вызовах], отличное от обычного C. Если это так, то решением было бы обернуть код для метода в extern "C" блок, подобный этому:

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_Tune_add
...

#ifdef __cplusplus
}
#endif
1 голос
/ 21 февраля 2012

Просто угадай ... Твоя dll зависит от другой dll, которой нет на пути?Модули MinGW обычно зависят от конкретной библиотеки времени выполнения C.

0 голосов
/ 26 ноября 2013

Попробуйте использовать следующий пример для Windows: (помните, что имя класса Java должно совпадать с именем соответствующего файла)

Шаг 1. Создайте следующий файл Java (P.java):

class P
{
  static
  {
    // "P" is the name of DLL without ".dll"
    System.loadLibrary ("P");
  }

  public static native void f(int i);

  public static void main(String[] args)
  {
    f(1);
  }
}

Шаг 2. javac P.java

Шаг 3. javah P

Затем «javah» генерирует заголовочный файл «Ph»

Шаг 4.Создайте файл «P.def», включающий следующие две строки (этот файл определяет экспортируемые символы, в данном случае имя функции C):

EXPORTS
Java_P_f

Шаг 5. Создайте свой файл C (Pc):

#include "P.h"

JNIEXPORT void JNICALL Java_P_f(JNIEnv *env, jclass c, jint i)
{
  printf("%i\n",i);
}

Шаг 6. В командной строке Visual Studio определите следующие переменные:

set JAVA_HOME = путь JDK

set include =% include%;% JAVA_HOME% \ include;% JAVA_HOME% \ include \ win32

Шаг 7. Генерируйте DLL:

cl / LD Pc P.def

Шаг 8. Запустите JavaПрограмма:

Java P

(Примечание: P.dll и P.class находятся в одном каталоге)

0 голосов
/ 18 июля 2013

У меня была та же проблема, и у меня работал флаг -Wl, -kill-at.

...