Создание расширения PHP с использованием JVM, нужны идеи реализации - PullRequest
2 голосов
/ 14 марта 2011

Я нахожусь в процессе разработки расширения PHP5, которое вызывает класс Java с использованием JNI. Расширение и основные функции, делающие это, уже готовы и работают, как ожидается, в однопоточной (на процесс) среде. Таким образом, использование функций класса расширений в скрипте php в командной строке (php-cli) работает без проблем. Теперь, используя это расширение PHP в качестве модуля apache, я испытываю проблемы при создании JVM через JNI. Первый вызов с использованием модуля работает нормально, второй вызов (во время выполнения первого вызова, а также после завершения первого вызова) JVM не создается и возвращает код меньше 0 (JNI_ERR). Как я выяснил, есть ограничение, что я могу иметь только одну JVM за раз на процесс. Я тестирую и запускаю свой модуль, работающий под Apache, только с одним работником (с помощью переключателя -X).

Мой дизайн модуля на текущем этапе выглядит так:

  • Конструктор расширения создает JVM и выполняет некоторую инициализацию.
  • Затем у меня есть несколько методов для вызова и работы с классом java (например, передача параметров и т. Д.) И выполнения некоторых методов класса java.
  • Мой деструктор расширения освобождает все используемые ресурсы и уничтожает JVM, ранее созданную в конструкторе.

Ну, во-первых, я думаю, что все получится, но это не так. Не так, как сейчас. Поэтому я немного застрял в идеях, как решить эту проблему.

Мои вопросы: Где я должен создать JVM и как я могу правильно назвать его (JNI Env) в многопоточной среде (PHP как модуль Apache). Я думаю, что я должен создать JVM где-нибудь, используя JNI_CreateJavaVM при инициализации модуля, а затем использовать AttachCurrentThread / DetachCurrentThread?! Что происходит, если другой поток пытается подключиться к потоку JVM, но к нему уже подключен другой поток? Должен ли я сделать здесь какой-нибудь механизм блокировки? Или создать JVM в методе класса расширения, вызвать внутри этого метода все связанные с Java методы и уничтожить JVM в конце того же метода класса расширения? Мне не нравится эта идея вообще. Хотя я думаю, что это не решает проблему множественной JVM на процесс.

Надеюсь, все не станет слишком сложно.

Итак, в основном моя проблема в том, где реализовать вызовы создания / уничтожения JVM и как получить доступ к среде JNI для вызова методов класса Java. И последнее, но не менее важное: возможно ли в любом случае то, чего я пытаюсь достичь?

Некоторые подробности разработки: Моя платформа - Linux / Ubuntu Lucid 10.04 LTS, использующая Apache2 и PHP 5.2.16 (скомпилировано из исходного кода). Модуль и основные функции разработаны на C, Java JRE - 6.0.22 (загрузка Oracle).

1 Ответ

0 голосов
/ 15 марта 2011

Я бы создал экземпляр JVM во время загрузки модуля (функция _init(void) или что-то вызываемое apache) и уничтожил бы его на _fini.

Если я правильно помню, вы можете подключить несколько потоков через AttachCurrentThread к JVM. Но вам нужно убедиться, что возвращаемый указатель только используется в этом потоке. Я бы посоветовал использовать нить локальное хранилище для него. Вы можете инициализировать указатель с 0 при создании потока и выполнить присоединение при первом вызове функции новым потоком.

...