Я нахожусь в процессе разработки расширения 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).