Сбой вызова JNI с UnsatisfiedLinkError - PullRequest
1 голос
/ 06 декабря 2010

Я получаю UnsatisfiedLinkError при вызове функций C из JNI, хотя мои настройки кажутся правильными.Вот что я сделал:

Есть класс Java:

package com.mycompany.myproduct;

public class Foo {
    static {
        System.loadLibrary("external");
    }

    public void native do_foo();
}

Я поместил libexternal.so в LD_LIBRARY_PATH, скомпилировал класс и выполнил javah надЭто.Результирующий файл com_mycompany_myproduct_Foo.h:

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

#ifndef _Included_com_mycompany_myproduct_Foo
#define _Included_com_mycompany_myproduct_Foo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_com_mycompany_myproduct_Foo
 * Method:    do_foo
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_mycompany_myproduct_Foo_do_1foo(JNIEnv *, jobject);

Реализовано делегирование C в ctinative.c (не уверен, нужен ли там extern "C"):

#include "com_mycompany_myproduct_Foo.h"

#include "External.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     com_com_mycompany_myproduct_Foo
 * Method:    do_foo
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_mycompany_myproduct_Foo_do_1foo(JNIEnv *, jobject) {
    do_foo();   // this is a function that defined in External.h
}

#ifdef __cplusplus
}
#endif

Скомпилировано и получено ctinative.o:

gcc -x c -g -m64 -DUNIX=1 -DUSE_SBUF=1 -DMAIN_VERSION=0 -DC_VER=7 -I$(EXTERNAL_SDK_ROOT)/include -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux -o ctinative.o -c ctinative.c

Вот вывод nm ctinative.oU там нормально?):

0000000000000000 T Java_com_mycompany_myproduct_Foo_do_1foo
                 U do_foo

Поместил что ctinative.o в LD_LIBRARY_PATH.Теперь при вызове Foo.do_foo() я получаю UnsatisfiedLinkError:

java.lang.UnsatisfiedLinkError: com.mycompany.myproduct.Foo.do_foo()V
at com.mycompany.myproduct.Foo.do_foo(Native Method)

Если я удаляю ctinative.o из LD_LIBRARY_PATH, ошибка не меняется.Если я удаляю libexternal.so из LD_LIBRARY_PATH, тогда, конечно, я получаю:

java.lang.UnsatisfiedLinkError: no external in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at com.mycompany.myproduct.Foo.<clinit>

Есть идеи о том, что я делаю неправильно?

Ответы [ 2 ]

2 голосов
/ 07 декабря 2010

Хорошо, мой опыт работы с нативными библиотеками в Linux ограничен игрушечными тестами, однако я довольно широко использовал их в Windows. Я ожидаю, что механизм похож, но действовать осторожно:)

Java завершает вызов собственной функции Java_com_mycompany_myproduct_Foo_do_1foo() при выполнении метода fooInstance.do_foo(). Это нативная функция, которую нужно определить в libexternal.so (или в том, что вы выбрали для загрузки с loadLibrary()).

Если я правильно понимаю ваш вопрос, вы скомпилировали функцию Java_com_mycompany_myproduct_Foo_do_1foo() в ctinative.o, а реализация не появилась в libexternal.so. Вы можете проверить это с помощью objdump --dynamic-reloc libexternal.so.

Полагаю, вам нужно, чтобы ваша собственная реализация Java_com_mycompany_myproduct_Foo_do_1foo() была скомпилирована в libexternal.so, или же вы могли бы связать ctinative.o для создания библиотеки динамических ссылок, похожей на libctinative.so.

РЕДАКТИРОВАТЬ: Чтобы объединить точки, полный механизм будет:

  1. Ваш код Java вызывает loadLibrary() для файла .so, который реализует функцию Java_com_mycompany_myproduct_Foo_do_1foo(). Давайте назовем это libctinative.so.
  2. libctinative.so динамически загружает libexternal.so с помощью механизма динамического связывания O / S - вам не нужно делать ничего особенного, чтобы это произошло, кроме правильной компиляции и связывания libctinative.so
  3. Ваша программа работает правильно, без других проблем:)
0 голосов
/ 07 декабря 2010

У вас есть Java_com_mycompany_myproduct_Foo_do_1foo (), но собственный void do_foo (). Было ли do_1foo () его именем, когда вы генерировали файлы .h / .c? Если вы изменили его, вы должны восстановить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...