Я получаю 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.o
(с U
там нормально?):
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>
Есть идеи о том, что я делаю неправильно?