如何部署混合C ++ / Java(JNI)应用程序? [英] How can I deploy a mixed C++/Java (JNI) application?

查看:212
本文介绍了如何部署混合C ++ / Java(JNI)应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

tl; dr:C ++插件需要调用Java .jar库。



我正在为Qt应用程序编写一个Qt插件。插件需要调用现有的Java库。这需要跨平台(Win,Mac,Linux)和架构(32位和64位Intel,没有PPC)。



我有一个简单的 hello worldJNI示例编译和运行。我将CMake脚本更新为find_package(JNI REQUIRED)等,所以它编译jni.h头并动态链接到JVM库。



至少,CMake在找到在编译时使用的正确的JVM方面做得很好。它在运行时找到正确的JRE(jvm.dll等),因为我对用户计算机的控制较少。



当我发送我的用户的插件?他们将需要为正确的架构安装JRE。但这并不意味着JRE的lib目录(ies)将在它们的路径中。



在Windows上,64位JDK安装了jvm.dll,这似乎很麻烦, :

  C:\Program Files\Java\jre7\bin\server\jvm.dll 

但是32位JDK安装它:

  C:\Program Files(x86)\Java\jre7\bin\client\jvm.dll 
pre>

我理解PF与PFx86的区别,但服务器/客户端的东西我没有得到。这些实际上是不同的JRE?



如果我编译/链接到一个JRE版本,并且用户有不同的版本,它会工作吗?



我假设这在Linux / Mac上会更容易,但我还没有得到这么远。



任何帮助。我不打算使用JNI,但不能承受一个$ 2000的编译器把Java转换成一个本地代码库(不是我有任何来源),我听说gcj可能​​不是由任务(和可能

解决方案

仅适用于Windows的可能解决方案。



使用延迟的DLL加载功能构建QT插件



请参阅 DELAYLOAD 如何做到这一点,但它只是添加 /DELAYLOAD:jvm.dll Delayimp.lib 到链接器命令。这意味着当加载QT插件时,但是在需要的时候, jvm.dll 将不会被加载(注意它 require使用 LoadLibrary() GetProcAddress())。 (我不知道在Linux或Mac上是否有类似的功能)



提供一种机制来通知QT插件什么JRE使用



这可能是注册表值,配置文件或专门为插件的环境变量(绝对不是环境变量 JAVA_HOME JRE_HOME ,其他应用程序可能依赖)。示例环境变量:




  • DANQT_32_JRE_HOME = C:\Program Files(x86)\Java\jre7(对于32位JRE)

  • DANQT_64_JRE_HOME = C:\Program Files\Java\jre7(对于64位JRE)



QT Plugin修改它的PATH



在QT插件调用依赖于JRE的任何函数之前,修改它的 PATH 环境变量,例如在值的开头插入%DANQT_32_JRE_HOME%\bin\server;%DANQT_32_JRE_HOME%\bin\client; PATH 。这意味着当QT插件执行其需要JRE的第一个动作时,它将从插入的目录加载。 (64位的不同环境变量)。对于 bin \server bin \client 我的理解是,这些本质上是相同的,但 server 由于运行时性能原因在初始化时执行更多。



如果QT插件是基于JRE 6构建的,我不确定兼容性并安装了JRE 7。如果存在兼容性问题,则将其作为先决条件安装要求,或者如果允许(我不确定合法性),请使用QT插件运送 jvm.dll


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 Files\Java\jre7\bin\server\jvm.dll

But the 32-bit JDK installed it to:

C:\Program Files (x86)\Java\jre7\bin\client\jvm.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)\Java\jre7 (for 32-bit JRE)
  • DANQT_64_JRE_HOME=C:\Program Files\Java\jre7 (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%\bin\server;%DANQT_32_JRE_HOME%\bin\client; 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 bin\server and bin\client 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)应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆