lit*_*net 4 c++ java java-native-interface jvm
我得到了以下场景:C++ 服务器应用程序正在侦听传入的客户端连接。每次客户端连接尝试都会生成一个新会话。此会话将调用特定服务,具体取决于服务 id,该服务 id 在来自客户端的序列化数据中提供。一旦结果从服务到达,会话就会将数据发送到客户端。
该场景的缺陷在于,该服务是用 Java 实现的。
因此我的问题是:
我知道为此我需要一个 Java VM。并且因为 C++ 服务器类将首先从 Java 应用程序调用(通过 SWIG 生成的包装器),所以我想我可能会将这个应用程序的 VM 引用传递给我的服务器类(以及之后的会话)。
但:
通常,Java 应用程序在启动服务器后什么也不做。也许我将不得不让它保持空闲状态以保持 VM 引用处于活动状态?对于 C++ 和 Java 交互中对服务的并发调用(超出服务内部的正常并发处理),我有什么特别需要担心的吗?
例子:
//Java Service
public class JMyService{
public String loadContactInformation(int userid){
return "test";
}
}
//C++ (very simplified)
class Session{
public:
//[...]
void handleWrite(){
vm = getVMReference(); //is saved beforehand
if(serviceId == CONTACT_INFO){
//todo call JMyService.loadContactInformation
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经看到了这个问题,但我不得不承认,这个解决方案很难理解,而且还不清楚提问者想要达到什么目的。在这篇文章中,作者正在做一些与 Java 内置类型类似的事情,但似乎代码生成器不能用于自己的 Java 类型。我也知道可以生成一个新的 VM来完成这项工作,但如果可能的话,我想使用现有的VM。
编辑
到 1) 我不确定,但是jint JNI_OnLoad(JavaVM *vm, void *reserved);当我使用 C++ 服务器类加载库时,也许可以使用该方法来获取指向 VM 的指针。不幸的是,Oracle 文档没有解释这个问题。有人可能有这方面的经验吗?
如何在我的 Java 代码中获取对当前 VM 的引用?
JNI_GetCreatedJavaVMs获取JavaVM*参考。如果 JVM 已在当前进程中启动,则此函数通常返回一个正好包含一个 JVM 引用的数组。JavaVM->AttachCurrentThread使用在步骤 1 中获得的引用进行调用。如果当前线程已与 JVM 关联,则跳过此步骤。JavaVM->GetEnv以获取JNIEnv*当前线程的指针。使用JNIEnv结构,您将能够调用 JNI 函数,请参见下文。如何使用 C++ 中的 VM 引用实例化和调用 Java 服务类
JNIEnv->FindClass得到jclass你想要实例化一个Java类的引用。JNIEnv->GetMethodID以获取对类的构造函数的引用。默认构造函数(没有参数的构造函数)有"()V"签名。JNIEnv->NewObject传递jclass和jmethodID实例化给定的类。JNIEnv->CallObjectMethod以执行 Java 方法。obj参数是在步骤3中获得的对象引用,methodID参数是您要调用的方法GetMethodID。示例代码
JavaVM* vm;
jsize vmCount;
if (JNI_GetCreatedJavaVMs(&vm, 1, &vmCount) != JNI_OK || vmCount == 0) {
fprintf(stderr, "Could not get active VM\n");
return NULL;
}
JNIEnv* env;
jint result = vm->GetEnv((void**)&env, JNI_VERSION_1_6);
if (result == JNI_EDETACHED) {
result = vm->AttachCurrentThread((void**)&env, NULL);
}
if (result != JNI_OK) {
fprintf(stderr, "Failed to get JNIEnv\n");
return NULL;
}
jclass cls = env->FindClass("JMyService");
jmethodID ctor = env->GetMethodID(cls, "<init>", "()V");
jobject service = env->NewObject(cls, ctor);
jmethodID loadMethod = env->GetMethodID(cls, "loadContactInformation", "(I)Ljava/lang/String;");
jobject serviceResult = env->CallObjectMethod(service, loadMethod, userId);
return serviceResult;
Run Code Online (Sandbox Code Playgroud)
笔记
JavaVM*,jclass,jmethodID整个应用程序。JNIEnv*与线程相关联。它只能在一个线程内重用。| 归档时间: |
|
| 查看次数: |
1649 次 |
| 最近记录: |