使用JVM构建PHP扩展,需要实现思路

时间:2011-03-14 04:55:25

标签: php c jvm java-native-interface

我正在开发一个使用JNI调用Java类的PHP5扩展。到目前为止,扩展和执行此操作的核心功能已准备就绪,并且在单线程(每个进程)环境中按预期工作。所以在命令行(php-cli)上使用PHP脚本中的扩展类函数可以正常工作。 现在使用该PHP扩展作为apache模块,我遇到了通过JNI创建JVM的问题。使用该模块的第一次调用工作正常,第二次调用(第一次调用运行时以及第一次调用完成后),未创建JVM并返回少于0(JNI_ERR)的代码。正如我所知,这是一个限制,我每个进程一次只能有一个JVM。我只用一个工作器(使用-X开关)测试并运行运行apache的模块。

我在当前阶段的模块设计是这样的:

  • 扩展构造函数创建JVM并进行一些初始化。
  • 然后我有几个方法来调用和使用java类(比如传递参数等)并执行java类的一些方法。
  • 我的扩展析构函数释放所有使用的资源并销毁以前在构造函数中创建的JVM。

嗯,首先我认为,一切都会成功,但事实并非如此。不像现在这样实施。所以我有点坚持想法如何解决这个问题。

我的问题是: 我应该在哪里创建JVM,如何在线程环境(PHP作为Apache模块)中正确调用它(JNI Env)。我想我必须在模块初始化时使用JNI_CreateJavaVM在某处创建JVM,然后使用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 :(得分:0)

我会在模块加载时创建JVM实例(_init(void)函数或者apache自己调用的东西)并在_fini上销毁它。

如果我没记错的话,可以通过AttachCurrentThread将多个线程附加到JVM。但是您需要确保返回的指针仅在该线程中使用 。我建议使用线程本地存储。您可以在创建线程时使用0初始化指针,并在新线程的第一次调用函数中执行附加。