C调用java JNI_CreateJavaVM只能调用成功一次

程序小菜鸟 2017-09-17 07:09:12
再使用c语言调用java代码的时候,选择使用JNI,根据网上的提示已经能够正常跑了,
int mask_name( char* NAME, char * keyValue, char * weight )
{
/*
接下来,声明所有希望在程序中使用的变量。
JavaVMOption options[] 具有用于 JVM 的各种选项设置。
当声明变量时,确保所声明的JavaVMOption options[] 数组足够大,以便能容纳您希望使用的所有选项。
在本例中,我们使用的唯一选项就是类路径选项。
因为在本示例中,我们所有的文件都在同一目录中,所以将类路径设置成当前目录。
可以设置类路径,使它指向任何您希望使用的目录结构。*/
JavaVMOption options[4];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
/*JNIEnv *env 表示 JNI 执行环境。
JavaVM jvm 是指向 JVM 的指针,我们主要使用这个指针来创建、初始化和销毁 JVM。
JavaVMInitArgs vm_args 表示可以用来初始化 JVM 的各种 JVM 参数。*/

long status;
jclass cls;
jmethodID mid;
jstring square;


/*avaVMInitArgs 结构表示用于 JVM 的初始化参数。
在执行 Java 代码之前,可以使用这些参数来定制运行时环境。
正如您所见,这些选项是一个参数,而 Java 版本是另一个参数。
按如下所示设置了这些参数:*/

/*为 JVM 设置类路径,以使它能找到所需要的 Java 类。
在这个特定示例中,因为 Sample2.class 和Sample2.exe 都位于同一目录中,所以将类路径设置成当前目录。
我们用来为 Sample2.c 设置类路径的代码如下所示:*/
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.class.path=C:\\algorithmfordm.jar";
options[2].optionString = "-Djava.library.path=C:\\Program Files\\Java\\jdk1.7.0_03\\jre\\bin\\server"; //指定加载的so路径
options[3].optionString = "-verbose:NONE"; //用于跟踪运行时的信息
//options[1].optionString = "-verbose.jni";
//options[0].optionString = "-Djava.class.path=.";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version=JNI_VERSION_1_6;//jdk版本1.6
vm_args.nOptions = 4;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;


/*创建 JVM
处理完所有设置之后,现在就准备创建 JVM 了。先从调用方法开始
如果成功,则这个方法返回零,否则,如果无法创建 JVM,则返回JNI_ERR。*/

status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
printf("--------------------****%ld\n",status);
if (status != JNI_ERR)
{
/*
查找并装入 Java 类
一旦创建了 JVM 之后,就可以准备开始在本机应用程序中运行 Java 代码。
首先,需要使用FindClass() 函数查找并装入 Java 类,如下所示:
cls 变量存储执行FindClass() 函数后的结果,如果找到该类,则 cls 变量表示该Java 类的句柄,
如果不能找到该类,则 cls 将为零。
*/
cls = (*env)->FindClass(env, "com/wiseweb/algorithm/MobilePhoneFilterAlgorithm");
//(*env)->FindClass(env, "jni/JniTest");
printf("test1,cls=%d...\n",cls);

if(cls !=0)
{
/*
查找 Java 方法
接下来,我们希望用 GetStaticMethodID() 函数在该类中查找某个方法。
我们希望查找方法 intMethod,它接收一个 int 参数并返回一个 int。
以下是查找 intMethod 的代码:
*/
mid = (*env)->GetStaticMethodID(env, cls, "getModelMobilePhone", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
//mid = (*env)->GetStaticMethodID(env, cls, "getObjectMethod", "(Ljava/lang/Object;)Ljava/lang/Object;");

/*
mid 变量存储执行 GetStaticMethodID() 函数后的结果。
如果找到了该方法,则 mid 变量表示该方法的句柄。
如果不能找到该方法,则mid 将为零。
*/
if(mid !=0)
{
/*CallStaticIntMethod() 方法接受 cls(表示类)、mid(表示方法)以及用于该方法一个或多个参数。
在本例中参数是 int 5。*/
//char * p = "422202199109300010";
char showTime[20];
char * t = getTime(showTime);
jstring value = (*env) ->NewStringUTF(env , NAME);
//char *str = (char *)(*env)->GetStringUTFChars(env,value,0);
//printf("%s\n",str);
jstring keyvalue = (*env) ->NewStringUTF(env , keyValue);
jstring timevalue1 = (*env) ->NewStringUTF(env , t);
jstring quanzhi = (*env) ->NewStringUTF(env , weight);
square = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid,value,keyvalue,timevalue1,quanzhi);
//square = (*env)->CallStaticIntMethod(env, cls, mid,4);
char *str1 = (char *)(*env)->GetStringUTFChars(env,square,0);
//printf("%s\n",str1);
memset(NAME,0X00,11);
if(strcmp(NAME, str1) != 0){
int i ;
for(i = 0; i < strlen(str1); i++){
NAME[i] = str1[i];
}
}
}
}
if ((*env)->ExceptionOccurred(env)) {

(*env)->ExceptionDescribe(env);

}
jint end = (*jvm)->DestroyJavaVM(jvm);
printf("-------------00000000000--%d\n",end);
return 0;

}
else
{
return -1;

}




}


int main()
{
int k ;
for(k = 0; k < 3; k++){
char NAME[] = {"15007113427"};
char keyValue[] = {"457685645971234574"};
char weight[] = {"40"};
mask_name(NAME,keyValue,weight);
//printf("Hello world!%d\n",sizeof(NAME));
printf("-----------------------11111111111--------%s\n",NAME);

}
system ("pause");
return 0;
}
...全文
801 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
程序小菜鸟 2018-03-30
  • 打赏
  • 举报
回复
在执行c调用java的过程中只要执行一次JNI_CreateJavaVM,结束之后在执行DestroyJavaVM,不要把JNI_CreateJavaVM执行多次
哈哈aa 2018-03-02
  • 打赏
  • 举报
回复
你好,关于用jni调用java虚拟机,JNI_CreateJavaVM后,DestroyJavaVM,然后在JNI_CreateJavaVM出错了,返回-1,这个要怎么解决,还望指点一二,谢谢
程序小菜鸟 2017-09-21
  • 打赏
  • 举报
回复
因为代码开发的是dll文件 ,不能单独初始化, 我选择将java虚拟机做成静态,但是注销虚拟机这个操作就没法进行了。感谢大家的帮助,这个贴我结了!
Dobzhansky 2017-09-20
  • 打赏
  • 举报
回复
jvm 在进程内就是只能初始化一次的, 你把jvm寄宿从功能调用中分离出来单独初始化
  • 打赏
  • 举报
回复
直接通过命令行调用更简单: java -jar xxx.jar param1 param2... >out.txt 其中param1等是传入的命令行参数,数据可以作为参数传入,或者作为文件名传入。 然后通过读取out.txt获取它的运行结果。
赵4老师 2017-09-20
  • 打赏
  • 举报
回复
c语言通过读写临时文本文件,间接调用java写的读写相同临时文本文件并调用jar包的程序。
程序小菜鸟 2017-09-19
  • 打赏
  • 举报
回复
您好 , 跨语言并非我所愿,只是因为需求是这样的,本来运行IBM的optim的脱敏函数接口是用C语言开发的。但是客户需要我们用他们的算法,而且不给算法我们,只给我一个jar包让我们调用,现在大部分难点都慢慢解决了 ,但是卡在c语言重复调用jar包的问题上了,希望赵老师能给我提供一点思路
赵4老师 2017-09-18
  • 打赏
  • 举报
回复
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢? 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话,文本文件的格式问题可参考json或xml 共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的: ·进程之间松耦合 ·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。 ·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务,只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满) ·…… “跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边, 回头是“使用共享纯文本文件进行信息交流”的岸!

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧