我正在开发一个使用JNI调用Java类的PHP5扩展。到目前为止,扩展和执行此操作的核心功能已准备就绪,并且在单线程(每个进程)环境中按预期工作。所以在命令行(php-cli)上使用PHP脚本中的扩展类函数可以正常工作。
现在使用该PHP扩展作为apache模块,我遇到了通过JNI创建JVM的问题。使用该模块的第一次调用工作正常,第二次调用(第一次调用运行时以及第一次调用完成后),未创建JVM并返回少于0(JNI_ERR
)的代码。正如我所知,这是一个限制,我每个进程一次只能有一个JVM。我只用一个工作器(使用-X
开关)测试并运行运行apache的模块。
我在当前阶段的模块设计是这样的:
嗯,首先我认为,一切都会成功,但事实并非如此。不像现在这样实施。所以我有点坚持想法如何解决这个问题。
我的问题是:
我应该在哪里创建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下载)。
答案 0 :(得分:0)
我会在模块加载时创建JVM实例(_init(void)
函数或者apache自己调用的东西)并在_fini
上销毁它。
如果我没记错的话,可以通过AttachCurrentThread
将多个线程附加到JVM。但是您需要确保返回的指针仅在该线程中使用 。我建议使用线程本地存储。您可以在创建线程时使用0初始化指针,并在新线程的第一次调用函数中执行附加。