Java: повторно использовать нативную библиотеку, уже загруженную?

Отказ от ответственности Не носитель английского языка, не стесняйтесь редактировать при необходимости.

У меня есть похожая проблема, которая объяснена здесь: java.lang.UnsatisfiedLinkError: Собственная библиотека XXX.so уже загружена в другой загрузчик классов

Я пытаюсь следовать ответу пользователя 2543253. Но мне действительно не хватает знаний в Java, и контекст немного другой.

связи

  1. .dll уже загружен в другой загрузчик классов? Кажется, также связано с этим вопросом.
  2. https://github.com/PatternConsulting/opencv/issues/7 Аналог.
  3. https://cycling74.com/articles/mxj-class-loading Объясняет поведение загрузчика классов MXJ

контекст

Редактировать: Не уверен, что этот контекст действительно важен, похоже, это та же проблема, что описана в ссылке 1.

Я хочу использовать OpenCV внутри приложения под названием Max/MSP.

Чтобы дать представление, это выглядит так:

Max / MSP позволяет пользователю собирать Patch, соединяя вместе несколько объектов, которые называются внешними, большинство из них написаны на C, но вы также можете создавать внешние на Java. Для этого вам нужно создать их экземпляр с помощью объекта "mxj". Например, если мой класс Java называется TestOpenCV, я создам поле и помещу "mxj TestOpenCV" внутрь.

OpenCV кажется правильно реализованным, например, я могу создать экземпляр объекта Mat и опубликовать его содержимое в консоли Max.

Проблемы появляются, когда я изменяю код Java объекта mxj. Чтобы обновить мой объект, я удаляю его и воссоздаю снова. Затем появляется та же самая проблема, которая объясняется здесь...

Max console возвращает это сообщение об ошибке:

java.lang.UnsatisfiedLinkError: Собственная библиотека C:\Windows\System32\opencv_java300.dll уже загружена в другой загрузчик классов по адресу java.lang.ClassLoader.loadLibrary1(неизвестный источник) по адресу java.lang.ClassLoader.loadLibrary0(неизвестный источник) в java.lang.ClassLoader.loadLibrary(Неизвестный источник) в java.lang.Runtime.loadLibrary0(Неизвестный источник) в java.lang.System.loadLibrary(Неизвестный источник) в OpenCVClassLoad.loadNativeLibrary(OpenCVClassLoad.java:5) в TestOpenCV. Java:22) (MXJ) не удалось выделить экземпляр TestOpenCV

Что я пробовал

Я попытался реализовать ответ пользователя 2543253. Он советует создавать крошечные классы, которые импортируют нативную библиотеку и экспортируют ее как JAR. Поэтому я создал новый проект Eclipse и добавил в него исходный файл.

import org.opencv.core.Core;

public class OpenCVClassLoad {
  public static void loadNativeLibrary() {
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  }
}

Я добавил openCV JAR в этот проект и экспортировал его как JAR.

Затем я изменил свой код в соответствии с тем, что объяснил пользователь2543253 (кода больше, я сохранил необходимое):

import com.cycling74.max.*;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;

public class TestOpenCV extends MaxObject {  
  static {
    // System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    OpenCVClassLoad.loadNativeLibrary();
  }

  public TestOpenCV(Atom[] args)
  {
    // ... 
  }

  public void notifyDeleted()
  {
    // ...
  }

  public void bang() {
    // Executed when I trig the little bang button you can see

    Mat m = new Mat(5, 9, CvType.CV_8UC4, new Scalar(0));
    post("OpenCV Mat: " + m);

    Mat mr1 = m.row(1);
    mr1.setTo(new Scalar(1));

    Mat mc5 = m.col(3);
    mc5.setTo(new Scalar(5));

    post("OpenCV Mat data:\n" + m.dump()); 
  }
}

Конечно, но это немного странно, чтобы правильно построить этот проект, я сохранил JAR из OpenCV в пути сборки:

Как вы можете видеть, я также добавил крошечный класс в путь сборки проекта. После всех этих модификаций объектный стиль mxj загружается правильно с первого раза, и метод bang() все еще работает, но проблема все еще существует. На самом деле это ничего не меняет в прошлой ситуации: если я изменяю код Java, удаляю объект в Max и создаю новый, появляется ошибка...

Вопрос

Существует много SO вопросов, касающихся одного и того же типа задачи, но контекст всегда разный, и мне сложно понять, что делать, особенно с моими базовыми знаниями Java.

Обходной путь должен состоять в том, чтобы просто повторно использовать эту библиотеку, уже загруженную, нет? но как этого добиться? Потому что, если я проверяю, что библиотека уже загружена, я делаю это с помощью Try / Catch, если больше ничего не делаю. Внешние действия, как если бы библиотека никогда не была загружена...

Как использовать эту нативную библиотеку? (Конечно, любое альтернативное решение этого приветствуется)

1 ответ

Просто удали второйOpenCVClassLoad.loadNativeLibrary(); в вашем bang() метод. В простом приложении Java код в static блок выполняется только один раз.

Кроме того, вы можете указать расположение собственной библиотеки в Eclipse вместо загрузки библиотеки через исходный код Java.

Другие вопросы по тегам