How can I deploy a mixed C++/Java (JNI) application?(如何部署混合 C++/Java (JNI) 应用程序?)
问题描述
tl;dr: C++ plugin needs to call Java .jar library. How to deploy this to users without too much headache?
I'm writing a Qt plugin for a Qt application. The plugin needs to make calls to an existing Java library. This needs to work cross-platform (Win, Mac, Linux) and architecture (32-bit and 64-bit Intel, no PPC).
I got a simple "hello world" JNI example compiling and running. I updated the CMake script to "find_package(JNI REQUIRED)" etc. so it compiles against the jni.h header and dynamically links against the JVM library.
On Windows at least, CMake does a good job of finding the right JVM to use at compile time. It's finding the right JRE (jvm.dll, etc.) at runtime that concerns me, since I have less control over user's computers.
How will it work when I send the plugin to my users? They will need a JRE installed for the proper architecture. But that doesn't mean the JRE lib directory(ies) will be in their path. If they're not, the plugin just bails out and doesn't load.
It also seems troublesome that on Windows, the 64-bit JDK installed jvm.dll to:
C:Program FilesJavajre7inserverjvm.dll
But the 32-bit JDK installed it to:
C:Program Files (x86)Javajre7inclientjvm.dll
I understand the PF vs. PFx86 difference, but the server/client thing I don't get. Are these actually different JREs?
Will it work if I have compiled/linked against one JRE version and the user has a different version?
I assume this will all be easier on Linux/Mac, but I haven't gotten that far yet.
Any help is appreciated. I'm not tied to using JNI, but can't afford a $2000 compiler to turn the Java into a native code library (not that I have the source anyhow), and I hear gcj may not be up to the task (and probably wouldn't help much on Windows).
A possible solution for Windows only.
Build the QT plugin using the delayed DLL load feature
See DELAYLOAD on how to do this but it is just adding /DELAYLOAD:jvm.dll
and Delayimp.lib
to the linker command. It means that the jvm.dll
will not be loaded when the QT plugin is loaded but at the point it is required (note it does not require using LoadLibrary()
and GetProcAddress()
). (I don't know if there is a similar feature on Linux or Mac)
Provide a mechanism to inform the QT plugin of what JRE to use
This could be either a registry value, a configuration file or an environment variable specifically for the plugin (definitely not environment variables JAVA_HOME
or JRE_HOME
that other applications may depend on). Example environment variables:
- DANQT_32_JRE_HOME=C:Program Files (x86)Javajre7 (for 32-bit JRE)
- DANQT_64_JRE_HOME=C:Program FilesJavajre7 (for 64-bit JRE)
QT Plugin Modify its PATH
Before the QT plugin invokes any functions dependent on the JRE it modifies its PATH
environment variable by inserting, for example, %DANQT_32_JRE_HOME%inserver;%DANQT_32_JRE_HOME%inclient;
at the start of the value for PATH
. This means when the QT plugin performs its first action that requires the JRE it will be loaded from the inserted directories. (Different environment variables for 64-bit). As for binserver
and binclient
my understanding is that these are essentially the same but the server
performs more during initialisation for runtime performance reasons.
I am unsure of compatibility if the QT plugin was built against JRE 6 and JRE 7 was installed. If there are compatibility issues then make it a prerequisite installation requirement or, if permitted (I am unsure of legalities), ship the jvm.dll
with the QT plugin.
这篇关于如何部署混合 C++/Java (JNI) 应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何部署混合 C++/Java (JNI) 应用程序?
基础教程推荐
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01