Использование собственных библиотек с Tomcat 9 с несколькими веб-приложениями - java .lang.UnsatisfiedLinkError - PullRequest
1 голос
/ 17 июня 2020

У меня есть собственная библиотека 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 написаны правильно.

Кто-нибудь может мне помочь, я чувствую, что схожу с ума!

1 Ответ

0 голосов
/ 19 июня 2020

Ваша функция не отображается в библиотеке. Заголовочный файл, который javac -h создает для вас, объявляет JNIEXPORT для всех встроенных функций, который для компиляторов GNU расширяется до visibility("default"). Но вы не включили этот заголовок, поэтому компоновщик не экспортирует эту функцию (и, следовательно, ваш процесс Java не может ее найти).

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