C++ 访问JVM调用java代码
主程序有C++启动,C++调用java接收字符串,然后c++ 对接收到的字符串进行分词,分词后的结果再返回给java程序。
C++代码
// Defines the entry point for the console application.
//
#include <stdlib.h>
#include <iostream>
#include <jni.h>
#include "Xml4nlp.h"
#include "Ltp.h"
using namespace std;
static XML4NLP xml4nlp;
static LTP ltp(xml4nlp);
string parse(string sentence) {
ofstream log_file("test.log");
cout << "Input sentence is: " << sentence << endl;
xml4nlp.CreateDOMFromString(sentence);
ltp.crfWordSeg();
ltp.postag();
ltp.ner();
ltp.gparser();
ltp.srl();
int wordNum = xml4nlp.CountWordInDocument();
for (int i = 0; i < wordNum; ++i) {
const char* word = xml4nlp.GetWord(i);
if (word != NULL) {
log_file << word << " ";
}
}
string result;
xml4nlp.SaveDOM(result);
cout << "Result is: " << result << endl;
xml4nlp.ClearDOM();
return result;
}
jstring str2jstring(JNIEnv* env, const char* pat) {
//定义java String类 strClass
jclass strClass = (env)->FindClass("Ljava/lang/String;");
//获取String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>",
"([BLjava/lang/String;)V");
//建立byte数组
jbyteArray bytes = (env)->NewByteArray(strlen(pat));
//将char* 转换为byte数组
(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
// 设置String, 保存语言类型,用于byte数组转换至String时的参数
jstring encoding = (env)->NewStringUTF("GB2312");
//将byte数组转换为java String,并输出
return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}
std::string jstring2str(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("GB2312");
jmethodID mid = env->GetMethodID(clsstring, "getBytes",
"(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0) {
rtn = (char*) malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
std::string stemp(rtn);
free(rtn);
return stemp;
}
string receive(jmethodID mid,JNIEnv *env, jclass cls) {
string ret;
if (mid != 0) {
jstring read = (jstring) env->CallStaticObjectMethod(cls, mid);
//printf("Result of read: %s\n", read);
string read1 = jstring2str(env, read);
ret = parse(read1);
}
return ret;
}
void send(jmethodID mid,JNIEnv *env, jclass cls,string ret) {
if (mid != 0) {
const char* pat=ret.c_str();
jstring arg = str2jstring(env, pat);
env->CallStaticObjectMethod(cls, mid, arg);
//env->ReleaseStringUTFChars(arg, pat);
}
}
int main(int argc, char *argv[]) {
cout << "Begin ..." << endl;
JavaVMOption options[1];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
jint square;
jboolean not1;
jstring read;
options[0].optionString = (char *) "-Djava.class.path=./classes/activemq-all-5.7.0.jar:./classes";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;
status = JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);
if (status != JNI_ERR) {
cls = env->FindClass("Server");
if (cls != 0) {
mid = env->GetStaticMethodID(cls, "await", "()V");
if (mid != 0) {
env->CallStaticObjectMethod(cls, mid);
printf("await ok \n");
}
jmethodID rmid = env->GetStaticMethodID(cls, "readReceive",
"()Ljava/lang/String;");
jmethodID smid = env->GetStaticMethodID(cls, "putRet",
"(Ljava/lang/String;)V");
for (;;) {
string ret = receive(rmid,env, cls);
send(smid,env,cls,ret);
}
} else {
printf("cls==0 \n");
}
jvm->DestroyJavaVM();
return 0;
} else {
printf("JNI_ERR,%d", status);
return -1;
}
}
需要注意的是GetStaticMethodID 第二个参数是方法签名,可以通过jps -s ClassName获取。
Java代码
//package com.datou.analysis.service.cosinecluster;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* Created with IntelliJ IDEA.
* User: lixiaoming@qmadou.com
* Date: 13-4-17
* Time: 下午2:06
* To change this template use File | Settings | File Templates.
*/
public class Server {
static BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10240);
static AdapterMQMsgSnder snder = null;
public static void await() {
MessageService messageService = new MessageService();
messageService.setUrl("tcp://localhost:61616");
messageService.setUser("admin");
messageService.setPassword("datuu_datuu");
snder = new AdapterMQMsgSnder();
snder.setQname("MSG_RES");
snder.setMessageService(messageService);
final MQMsgRcver rcver = new MQMsgRcver();
rcver.setQname("MSG_REQ");
rcver.setService(messageService);
Thread tt = new Thread(){
public void run(){
for(;;){
try {
System.out.println("rcvMsgQ begin");
String resMsgEntity = rcver.rcvMsgQ();
if (resMsgEntity != null) {
queue.put(resMsgEntity);
System.out.println("get reslt_ok");
}
System.out.println("rcvMsgQ end");
} catch (Exception e) {
e.printStackTrace();
rcver.closeConnection();
Util.sleepSecs(3);
}
}
}
} ;
tt.setDaemon(true);
tt.start();
}
public static String readReceive(){
String ss = null;
try {
ss = queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return ss;
}
public static void putRet(String ret){
System.out.println("putRet ["+ret+"]");
snder.sendMsgQ(ret);
}
}
注意 java中使用线程时候,一定要tt.setDaemon(true);否则程序会阻塞。
分享到:
相关推荐
在提供的资源"使用C++创建java虚拟机JVM,使用JNI调用java函数"中,可能详细介绍了以上步骤的实际应用,包括代码示例和可能遇到的问题及解决方案。通过学习和实践这个教程,开发者可以更好地理解和掌握C++与Java之间...
在本文中,我们将深入探讨如何在Visual Studio 2019环境下使用C++通过Java Native Interface (JNI)来调用Java代码。JNI是Java平台的一部分,它为Java应用程序提供了与本地代码交互的能力,使得开发者可以将Java应用...
同样,C++也可以通过JNI调用Java的方法。 在Qt中,可以使用QProcess或其他I/O组件来启动JVM并传递参数,以执行Java代码。同时,可以使用信号和槽机制来协调C++和Java之间的事件处理。 为了在实际项目中实现这一...
在C++中调用Java代码,一般会用到JNI(Java Native Interface),它提供了一种方式让Java代码可以调用本地(Native)代码,反之亦然。 - JNI定义了一套函数,使得C/C++可以创建Java对象,调用Java方法,处理异常等...
- 通过`JNIEnv`指针,C++可以查找并调用Java对象的方法,访问字段,甚至创建新的Java对象。 8. **构建流程**: - 使用NDK(Native Development Kit)编译C/C++代码,生成.so文件。 - 将.so文件放置在项目的`jni...
本教程将详细讲解如何在Visual Studio 2019环境下,利用C++通过Java Native Interface (JNI) 调用Java代码。首先,我们需要了解JNI的概念和作用。 JNI是Java平台提供的一种接口,允许Java代码和其他语言写的代码...
首先,C++调用Java主要依赖于Java Native Interface(JNI),这是Java平台标准的一部分,允许Java代码和其他语言写的代码进行交互。JNI为C/C++提供了接口,使得它们可以调用Java的方法,反之亦然。 **JNI基本概念**...
JNI是Java提供的一种机制,使得本地(Native)代码(如C++)能够与Java虚拟机(JVM)通信,调用Java类和方法。 在压缩包中的文件列表中,我们看到: 1. `FunCall_C2Java_Callee.jar` - 这是一个Java编译后的可执行...
易语言与Java的交互通常依赖于Java本地接口(JNI),这是一种让Java代码调用本地(如C、C++或易语言)代码,反之亦然的机制。JNI提供了一套接口,允许Java代码生成特定平台的原生代码,这样就可以直接与操作系统或...
它也允许C++代码调用Java对象的方法,访问和修改Java对象的字段,以及处理Java数组。 二、C++调用Java的步骤 1. **编写Java类**:首先,你需要一个包含要被C++调用的Java方法的类。这个类通常会包含一个`native`...
在C或C++中调用JAVA方法是一种常见的跨语言交互技术,主要依赖于Java Native Interface (JNI)。JNI是Java平台的一部分,它允许Java代码和其他语言编写的代码进行交互,从而实现混合编程。JNI提供了丰富的API,使得...
JNI允许Java代码调用本地(如C/C++或Delphi)代码,反之亦然。 1. **安装Java JDK**:首先,确保你已经在你的系统上安装了Java Development Kit (JDK),因为Delphi需要与JVM进行交互,而JDK包含了必要的头文件和库...
Java Native Interface (JNI) 是Java平台提供的一种机制,允许Java代码和其他语言写的代码进行交互。本教程将详细讲解如何将C++库封装为JNI接口,以便于Java程序调用。 首先,了解JNI的基本概念。JNI是一套接口,它...
这将定义C/C++函数原型,这些函数将在C++代码中实现,用于调用Java方法。 2. **编写C++代码**:在生成的头文件中,你可以看到Java方法的本地接口。在C++源文件(如`Interface.cpp`和`MyFunction.cpp`)中实现这些...
在C/C++中调用Java代码,主要依赖于Java Native Interface (JNI),这是一个允许Java代码与本地代码交互的标准接口。JNI使得开发者可以将C/C++的高性能代码集成到Java应用程序中,或者从C/C++程序中调用Java的类和...
这时,我们可以使用Java Native Interface (JNI) 来实现Java代码与C++代码的交互。JNI允许Java应用程序调用或者被C/C++代码调用,形成了跨语言的桥梁。 标题“java调用c++生成so库”指的是在Linux环境下,通过JNI...
**JNI(Java Native Interface)** 是Java平台的一部分,它允许Java代码与其他语言写的代码进行交互,尤其是C和C++。JNI是Java与本地代码之间沟通的桥梁,使得Java应用程序能够调用本地库中的方法,同时也支持从本地...
- 导入库:C++代码需要链接到libjvm.so库(在Unix-like系统上)或jvm.dll(在Windows上)来访问Java虚拟机(JVM)的内部功能。 - Java类和方法ID:JNI提供函数来获取Java类的实例和方法ID,这是调用Java方法的关键...
在Java代码中,我们可以添加一个`sayHelloFromJava`方法,以便在C++回调时调用: ```java public class HelloJni { // ... public void sayHelloFromJava() { System.out.println("Hello from Java!"); } ...
在Java应用程序中,JNI允许Java代码与用C、C++等本地语言编写的代码进行交互,实现了Java虚拟机(JVM)与本地代码的无缝连接。JNI在各种场景下都有广泛应用,例如性能优化、利用现有库、硬件访问等。 在这个“jni....