У меня есть собственная библиотека JNI, которую я скомпилировал на своей машине с Ubuntu 20.04 - назовем ее JNI.so. У меня также есть 2 разных веб-приложения Spring Boot, которые я развертываю на своем сервере Tomcat 9 - оба из которых нуждаются в доступе к этому файлу библиотеки. Следуя инструкциям здесь , я пробовал как добавить JniLifecycleListener на мой сервер. xml файл конфигурации, так и программно вызвать org. apache .tomcat.jni.Library.loadLibrary. Хотя моя цель - получить доступ к этой нативной библиотеке двум веб-приложениям, чтобы просто отладить эту проблему, я ограничился одним веб-приложением, пока не начну работать. Вот как выглядит мой класс java:
package com.example.hellojni;
public class HelloJni {
public native String stringFromJNI();
public String test() {
return stringFromJNI();
}
}
А вот код C:
#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
Скомпилирован со следующим:
gcc -c -fPIC hello-jni.c -o hello-jni.o -I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux
gcc hello-jni.o -shared -o libJNI.so
Я также поместил свой файл JNI.so в $ CATALINA_HOME / shared / lib и добавил следующее в мой файл catalina.properties (как указано здесь ):
shared.loader="${catalina.base}/shared/lib", "${catalina.base}/shared/lib/*.jar"
С строка JniLifecycleListener в моем файле server. xml, при загрузке tomcat я вижу следующие данные журнала:
17-июн-2020 15: 32: 06.266 INFO [main] org. apache .catalina.startup.Catalina.load Инициализация сервера за [705] миллисекунды
17 июня 2020 г. 15: 32: 06.267 INFO [main] org. apache .catalina.core.JniLifecycleListener .lifecycleEvent Загруженная собственная библиотека [JNI]
17-июн-2020 15: 32: 06.329 INFO [main] org. apache .catalina.core.StandardService.startInternal Запуск службы [Catalina]
17-июн-2020 15: 32: 06.331 INFO [main] org. apache .catalina.core.StandardEngine.start Внутренний запуск двигателя сервлета: [Apache T * 102 8 *
Однако, когда я пытаюсь получить доступ к библиотеке из контроллера Spring Boot со следующим кодом:
System.out.println(new HelloJni().test());
, я получаю следующую ошибку:
java.lang.UnsatisfiedLinkError: com.example.hellojni.HelloJni.stringFromJNI()Ljava/lang/String;
at com.example.hellojni.HelloJni.stringFromJNI(Native Method) ~[classes/:0.0.1-SNAPSHOT]
at com.example.hellojni.HelloJni.test(HelloJni.java:9) ~[classes/:0.0.1-SNAPSHOT]
at com.company.MyApplication.controllers.DashboardController.dashboard(DashboardController.java:51) ~[classes/:0.0.1-SNAPSHOT]
Теперь мне кажется, что я перепробовал все решения, которые мне удалось найти в Интернете, и все они дали примерно одинаковые результаты. Я попытался полностью отказаться от использования JniLifecycleListener и вместо этого вернулся к этому популярному решению, которое, похоже, предшествовало Tomcat 7, но с точно такими же результатами. Я попытался найти файл .so в $ CATALINA_HOME / lib вместо shared / lib с аналогичными результатами.
Единственный способ, которым я смог добиться какого-либо прогресса, - это отказаться от JniLifecycleListener, вызвав обычную систему .loadLibrary () в блоке кода stati c внутри JAR, который я упаковал и поместил в shared / lib вместе с файлом .so, а затем вызвал вызов собственного метода. Однако это работает только в случае использования метода stati c или раздела кода stati c, который загружает библиотеку. Думаю, по крайней мере, это подтвердило, что мои библиотеки JNI написаны правильно.
Кто-нибудь может мне помочь, я чувствую, что схожу с ума!