DLL для динамической программы Java? - PullRequest
3 голосов
/ 05 января 2011

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

Моя идея состояла в том, чтобы создать DLL для каждого из классов форматирования, и чтобы мое приложение передавало данные для преобразования в каждый из них. Таким образом, позже я могу создать DLL и получить к ней доступ к основному приложению. (Я бы с удовольствием выслушал любые альтернативные способы сделать это, поскольку кто-то, кто делал это на C ++ / C # до этого, чувствовал себя логичным решением, но оно может быть неприменимо к Java)

Моя проблема в том, что я абсолютно не знаю, как это сделать - в C ++ / C # я мог бы написать это в несколько строк кода, но я не уверен, как это работает с Java. Как я могу это сделать, рискуя задать ужасно неопределенный вопрос?

Ответы с благодарностью и печенье и чай будут предложены. :)

Заранее спасибо, M

Редактировать: Извините, просто добавляю: я также не уверен, как создать DLL, которая должна быть на Java для этого проекта, для чтения в первую очередь. Благодарю. :)

Ответы [ 6 ]

5 голосов
/ 05 января 2011

Вместо того, чтобы использовать DLL как таковую, создается впечатление, что требуется какая-то архитектура плагинов.

Одна из причин, по которой я бы не рекомендовал использовать DLL, если в этом нет необходимости, заключается в том, что для связывания кода Java с собственным кодом потребуется использование собственного интерфейса Java (JNI), что, вероятно, потребует больше усилий, чем чисто Java решение.

Одним из относительно простых способов сделать это является использование отражений возможностей Java.

Исходя из предоставленной информации, я бы, вероятно, согласился со следующим:

  1. Определить интерфейс для выходного формата.
  2. Создайте класс Java, реализующий интерфейс.
  3. Получить класс можно по classpath .
  4. Динамически загружать класс с помощью отражения. (С помощью метода Class.newInstance можно создавать объекты из файлов class, загруженных ClassLoader.)

С этими шагами можно было бы реализовать упрощенный плагин, который не потребовал бы полной перестройки, когда требуется поддержка нового формата.


Шаг 1: определить интерфейс

Допустим, мы получили интерфейс, подобный следующему:

public interface Outputter {
  public void write(Data d);
}

Шаг 2. Создание класса реализации

Затем мы создадим класс реализации.

public class TextOutputter {
  public void write(Data d) {
    // ... output data to text
  }
}

Затем, скомпилировав вышесказанное, мы получим файл class с именем TextOutputter.class.

Шаг 3: Сделать класс доступным из classpath

При запуске основного приложения нам потребуется указанная выше TextOutputter.class в classpath . Обычно нужно сообщить JVM список мест, которые следует рассматривать как путь к классам, и он должен включать в себя указанный выше файл class.

Как только это будет сделано, мы сможем загрузить вышеуказанный класс, используя отражение.

Шаг 4: Динамически загрузить класс с помощью отражения

Теперь, когда мы действительно хотим загрузить вышеуказанный класс, мы сделаем что-то вроде следующего:

// Note: We load the class by specifying the fully-qualified class name!
Class<?> clazz = Class.forName("TextOutputter");

// Then, we instantiate the class.
// Note that the following method will call the no-argument constructor.
Outputter outputter = clazz.newInstance();      

// Now, we can give data to the TextOutputter object that we loaded dynamically.
outputter.write(...);

Метод Class.forName используется для попытки найти класс TextOutputter из значения по умолчанию ClassLoader. Как только мы получим класс как представление Class, мы сможем создать экземпляр объекта этого класса.

Создание объекта можно выполнить с помощью метода Class.newInstance. Если нужно использовать что-то иное, чем конструктор без аргументов, Constructor класса нужно будет получить, продолжая создавать экземпляр объекта оттуда.

Объект создается посредством отражения, затем помещается в переменную Outputter, поэтому метод write можно вызывать для TextOutputter.

Добавление большего числа форматов повлечет за собой описанный выше процесс, но изменение полного имени класса (например, для String, FQCN - java.lang.String) - это все, что необходимо для загрузки другого класса.


В двух словах, это то, что нужно для динамической загрузки class файлов и использования их из вашего приложения.

(Как примечание, на самом деле я не скомпилировал приведенный выше код, поэтому здесь и там могут быть некоторые ошибки, но я надеюсь, что смогу проиллюстрировать процесс, который он предпримет.)

2 голосов
/ 05 января 2011

Я сделал такие вещи. я создал открытую архитектуру плагинов на основе Java, основанную на POJO, которая даже обновлялась на лету обновленных классов плагинов JNI - это интерфейс для работы с нативным кодом. Единственной технической частью было переписать загрузчик классов, который позволял динамически перезагружать DLL во время выполнения. Но если вы делаете только «автономные» обновления, такие вещи не нужны.

1 голос
/ 05 января 2011

Java SE 6 представляет класс ServiceLoader: http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html

Если вам нужен правильный модульный подход, рассмотрите платформу NetBeans (особенно если это настольное приложение) или OSGi.

1 голос
/ 05 января 2011

Я думаю, вы можете игнорировать путь JNI. У меня сложилось впечатление, что вы используете термин dll из-за отсутствия лучшего слова, вам на самом деле не нужна dll.

Вы можете сделать то же самое в Java, но вы бы поместили свои фильтры в файлы jar вместо dll.

  1. Определить интерфейс для фильтров формата файла для реализации
  2. Поместите каждую реализацию в jar, в определенную папку (например, «фильтры»)
  3. В какой-то момент в приложении перебираем папку, генерируем загрузчик классов для jar
  4. Используйте отражение, чтобы найти все реализации вашего интерфейса, и создайте класс для каждого
  5. Назовите методы, чтобы сделать свою работу

Вот и все.

1 голос
/ 05 января 2011

Вы можете загрузить новую DLL в любое время с помощью System.loadLibrary (). Однако вам может потребоваться загрузить класс Java для привязки к нему.

Может оказаться полезным использование контейнера OSGi, поскольку он поддерживает как загрузку, так и выгрузку модулей (включая общие библиотеки)

Я бы предложил использовать karaf с iPOJO, но есть много других.

1 голос
/ 05 января 2011

Если вы хотите написать нативные коды (скомпилированные в DLL) для использования в Java, вы должны посмотреть на Собственный интерфейс Java (JNI) .

Обновление вы можете использовать System.loadLibrary(String libName) (если вы знаете, что имя библиотеки и путь к ней задан) или System.load(String filename) (имя библиотеки) для загрузки библиотеки (DLL) в Java.

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