2015-03-06 3 views
2

java.lang.UnsatisfiedLinkError при использовании JNI.java.lang.UnsatisfiedLinkError при использовании JNI на ubuntu

Мои испытания окружающей среды:

Ubuntu 12.04/64-bit
JDK 1.7
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5)

Это мой источник Java:

public class HelloJNI { 
    static { 
     //System.loadLibrary("libHelloJNI"); 
    } 

    private native void sayHello() ; 

    public static void main(String[] args){ 
     //System.getProperties().list(System.out); 
     String lib_path = System.getProperty("java.library.path"); 
     System.out.println("java.library.path=" + lib_path); 

     System.loadLibrary("libHelloJNI"); 

     HelloJNI myJNI = new HelloJNI(); 
     myJNI.sayHello(); 
    } 
} 

Это мой источник C:

#include <stdio.h> 
#include "HelloJNI.h" 

JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) 
{ 
    puts("Hello Momo. This is C code."); 
    return; 
} 

Это мой Makefile:

JNI_INC=-I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" 

JNI_LIB=libHelloJNI.so 
JNI_OUT=$(JNI_LIB) HelloJNI.h HelloJNI.class 
CFLAGS= $(JNI_INC) -fPIC -shared 

all: $(JNI_OUT) 

HelloJNI.h: HelloJNI.class 
    javah -jni HelloJNI 

$(JNI_LIB): HelloJNI.c HelloJNI.h 
    gcc $(CFLAGS) -o [email protected] HelloJNI.c 

HelloJNI.class: HelloJNI.java 
    javac HelloJNI.java 

run: 
    java HelloJNI 
    #java -Djava.library.path=. HelloJNI 

clean: 
    rm $(JNI_OUT) 

Когда я запустить приложение Java, старая проблема возникает:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 java.library.path=.:/home/mancook/cook/work/StSoftware/src/java/StTestJni/tutor01_HelloJNI:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Exception in thread "main" java.lang.UnsatisfiedLinkError: no libHelloJNI in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1088)
at HelloJNI.main(HelloJNI.java:22)
make: *** [run] Error 1

Я гугл Интернета для этой проблемы и найти, что это OLD вопрос. Но я НЕ МОЖЕТ найти любой способ исправить мою проблему !! Надеюсь, кто-нибудь может мне помочь. Заранее спасибо.

+0

Не могли бы вы также вставить свой родной файл, 'HelloJNI.c'? Это облегчило бы людям воспроизводить это. –

+1

Вам нужно '-Djava.library.path' фактически включить каталог, содержащий' libHelloJNI.so'. –

+0

#include #include #include "HelloJNI.h" JNIEXPORT недействительными JNICALL Java_HelloJNI_sayHello (JNIEnv * ENV, jobject thisObj) { \t Е ("Привет Момо Это код С."); \t возвращение; } – mancook

ответ

1

Вам не нужны -Djava.library.path=. в Makefile, и вам необходимо загрузить библиотеку с System.loadLibrary("HelloJNI"); - не lib префикса, не .so суффикса. Префикс и суффикс обрабатываются Java - подумайте об этом, схема именования в Windows отличается (глупо, но факт). И остерегайтесь ловушки, что у вас есть System.loadLibrary() два раза в вашем коде, если вы измените только один из них, он все равно потерпит неудачу. Это на самом деле стоило мне нескольких минут: P

P.S .: Я предлагаю несколько изменений в Makefile. Я бы использовал $(RM) вместо rm. Цели, которые не являются файлами, должны быть объявлены .PHONY. Переменные, которые не относятся к автоматическим переменным, могут быть назначены := вместо =. Я бы использовал отдельный шаг для создания .so из файла .o. Я бы использовал правило шаблона для компиляции Java, например %.class: %.java. Я бы использовал правило шаблона для создания файла заголовка, например %.h: %.class. Материал -I должен быть в CPPFLAGS не CFLAGS, потому что он предназначен для препроцессора. -shared должен затем перейти в LDFLAGS и так далее ...

Вот ваш новый Makefile:

CPPFLAGS:=-I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" 

JNI_LIB:=libHelloJNI.so 
JNI_OUT:=$(JNI_LIB) HelloJNI.o HelloJNI.h HelloJNI.class 
CFLAGS:=-fPIC 
LDFLAGS:=-shared 

.PHONY: all 
all: $(JNI_OUT) 

%.h: %.class 
    javah -jni HelloJNI 

$(JNI_LIB): HelloJNI.o 
    $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o [email protected] 

HelloJNI.o: HelloJNI.c HelloJNI.h 

%.class: %.java 
    javac HelloJNI.java 

.PHONY: run 
run: 
    java -Djava.library.path=. HelloJNI 

.PHONY: clean 
clean: 
    $(RM) $(JNI_OUT) 
+0

Большое спасибо за вашу помощь :) Я думаю, что причиной неудачи является префикс 'lib' на Linux – mancook

+0

Да, это так :) И не забудьте принять ответ, если вы считаете, что это правильно. –