处女贴:linux下通过JNI用C/C++中调用JAVA类,java类添加依赖包后,c++无法调用,无法找到class

lianying16 2014-11-25 04:57:09
案例原帖 http://blog.sina.com.cn/s/blog_48eef8410100fjxr.html

照着这样的例子下来是可以调用的,但import一个简单依赖包后就无法调用了,cpp代码如下

#include <stdio.h>
#include <iostream>
#include <jni.h>
#include <stdlib.h>
#include <assert.h>
#include <cstring>


jstring stoJstring(JNIEnv* env, const char* pat)
{
jclass strClass = env->FindClass("java/lang/String");
jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
jbyteArray bytes = env->NewByteArray(strlen(pat));
env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
jstring encoding = env->NewStringUTF("utf-8");
return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
}


char* jstringTostring(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
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);
return rtn;
}

using namespace std;

int main()
{
JavaVMOption options[2];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
jint square;
jboolean jnot;
jobject jobj;
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.class.path=./;/home/grid/app/Test/lib/test.jar";
cout<<options[1].optionString<<endl;
//options[2].optionString = "-verbose:jni"; 用于跟踪运行时的信息
vm_args.version = JNI_VERSION_1_4; // JDK版本号
vm_args.nOptions = 2;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

if(status != JNI_ERR){
printf("create java jvm success\n");
cls = env->FindClass("com/test/MyTest"); // 在这里查找ava类
if(cls !=0){
printf("find java class success\n");
// 构造函数
mid = env->GetMethodID(cls,"<init>","(II)I");
if(mid !=0){
jobj=env->NewObject(cls,mid);
std::cout << "init ok" << std::endl;
}

// 调用add函数
mid = env->GetStaticMethodID( cls, "add", "(II)I");
if(mid !=0){
square = env->CallStaticIntMethod( cls, mid, 5,5);
std::cout << square << std::endl;
}


// 调用judge函数
}
else{
fprintf(stderr, "FindClass failed\n");
}

jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory.\n");
return 0;
}
else{
printf("create java jvm fail\n");
return -1;
}
}



Mytest.java
package com.test;

import rtest.Test;

public class Mytest {

static Test sb = new Test();

public static int add(int a, int b) {
return sb.ad(a, b) + a + b;
}

public boolean judge(boolean bool) {
return !bool;
}

public static void main(String[] args) {
System.out.println(add(5, 5));
}
}



Test.java
package rtest;

public class Test {

public int ad(int a, int b) {
return a + b;
}

}


java独立运行是成功的
c++调用就提示FindClass failed
在网上找了好多答案都是说启动参数要加上依赖包路径,可我加了还是一样
options[1].optionString = "-Djava.class.path=./;/home/grid/app/Test/lib/test.jar";

跪求大侠解答,在线等
...全文
301 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
lianying16 2014-11-26
  • 打赏
  • 举报
回复
引用 10 楼 xiaoS999 的回复:
options[1].optionString = "-Djava.class.path=./;/home/grid/app/Test/lib/test.jar"; 他妈的这里是用冒号分隔的你用分号???
卧槽大神啊,解决了困扰我多年的便秘。。
xiaoS999 2014-11-26
  • 打赏
  • 举报
回复
options[1].optionString = "-Djava.class.path=./;/home/grid/app/Test/lib/test.jar"; 他妈的这里是用冒号分隔的你用分号???
lianying16 2014-11-25
  • 打赏
  • 举报
回复
引用 4 楼 sniffer12345 的回复:
一般这种结构的API。。当你if(status != JNI_ERR){的时候,你可以getLastError看看到底是什么原因。一般会提示说缺了什么依赖的 楼主根据你的情况分析,你缺的依赖应该不仅仅是test.jar啊,应该还有其他的。比如“System.out.println”这个就需要io包了,但是没看到你指向jdk的路径
曾将jdk的classpath加了进去也不奏效 谢谢这位大侠回复,没用过getLastError,先研究下
sniffer12345 2014-11-25
  • 打赏
  • 举报
回复
一般这种结构的API。。当你if(status != JNI_ERR){的时候,你可以getLastError看看到底是什么原因。一般会提示说缺了什么依赖的 楼主根据你的情况分析,你缺的依赖应该不仅仅是test.jar啊,应该还有其他的。比如“System.out.println”这个就需要io包了,但是没看到你指向jdk的路径
lianying16 2014-11-25
  • 打赏
  • 举报
回复
如果对响应速度要求较高,读写文件就显得很慢了
赵4老师 2014-11-25
  • 打赏
  • 举报
回复
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢? 共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的: ·进程之间松耦合 ·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。 ·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务,只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满) ·……
目录 I. 目录 1 II. java c/cpp互相调用实例(姊妹篇之一)——java调用c/cpp 4 一 先制作一个系统有的DLL文件(cpp给出的sdk接口) 4 二 JNI 7 1、 编写java文件 7 2、 生成.h头文件 8 3、 用c/cpp实现这个头文件 9 三 测试 10 四 最后补充 11 III. java c/cpp互相调用实例(姊妹篇之二)——c/cpp调用java 11 一、 编写java代码 12 二、 编译java代码 12 三、 编写 C/C++ 代码 13 四、 运行exe 18 IV. Java JNI 编程进阶 18 一、 解决性能问题 18 二、 解决本机平台接口调用问题 19 三、 嵌入式开发应用(JNI小例子) 20 1、 新增一个基础 22 2、 定义新继承基础 23 3、 编写调用 23 4、 新增两个本地方法 24 5、 修改 RunMain 25 6、 新增一个方法处理java对象 26 7、 新增一个方法处理数组 29 8、 改写RunMain 32 四、 参考资料: 33 V. Eclipse+CDT+MinGW 进行JAVA调用C/C++ 34 一、 安装eclipse3.2。 34 二、 安装MinGW。 34 1、 下载MinGW 34 2、 安装 34 3、 安装版本 34 4、 选择安装的编译器 34 5、 选择安装路径,下一步 35 6、 等待下载软件 35 三、 MinGW的环境变量设置 35 1、 设置Path 35 2、 设置C_INCLUDE_PATH 35 3、 设置CPLUS_INCLUDE_PATH 35 四、 做一个小技巧修改 35 五、 安装CDT插件 36 1、 下载CDT插件 36 2、 安装CDT插件 36 六、 简单介绍CDT的使用吧 36 1、 新建一个C++项目 36 2、 输入New Project名字 36 3、 给项目新建一个的源文件 36 4、 接着出现文件添加的窗口,在File Name栏里面写上文件名 36 5、 编辑hello.cpp 37 6、 添加一个编译命令 37 七、 让我们开始进入真正的工作吧! 38 The Java side 38 1、 建立Java工程JavaHello,编写java 38 2、 用命令生成头文件 38 The C side-Compiling the Library 40 1、 建立标准C工程Cpro,并生成dll文件 40 1) 将生成的头文件test_Hello.h拷贝到C工程Cpro下 40 2) 编写CHello.c,内容为: 40 3) 在C工程Cpro下建立hello.def文件(用于定义导出的函数),内容为: 40 4) 在C工程Cpro下建立makefile文件,内容为: 40 5) Make Targets 40 6) Make Targets视图下双击step1,在C工程Cpro下生成hello.o 文件。 41 7) Make Targets视图下双击step1,在C工程Cpro下生成hello.dll 文件。 41 2、 JAVA调用DLL 41 1) 将hello.dll拷贝到Java工程JavaHello下。 41 2) 运行Hello.java,则可以看到输出结果: 41 1) 将Hello.c改为Hello.cpp 41 2) 将makefile内容改为: 41 3) 其他的几乎都不用改变也可以。 42 评论: 42 VI. c++如何调用java程序 51 DemoMain.java内容如: 51 采用vc6++ IDE,采用JNI技术实现。 51 1、 编译时 51 2、 运行时 51 程序的关键在 53 VII. JNI 53 一、 定义 53 二、 设计目的 54 三、 书写步骤 54 1) 编写java程序:这里以HelloWorld为例。 54 2) 编译 55 3) 生成扩展名为h的头文件 55 4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。 56 5) 生成动态库 56 6) 运行程序 java HelloWorld就ok. 56 四、 调用考虑的问题 56 1) java和c是如何互通的? 57 2) 如何将java传入的String参数转换为c的char*,然后使用? 57 3) 将c获取的一个char*的buffer传递给java? 57 4) 不知道占用多少空间的buffer,如何传递出去呢? 58 五、 对JAVA传入数据的处理 58 1) 如果传入的是bytearray的话,作如下处理得到buffer: 58 VIII. C/C++调用JAVA 58 一、 加载虚拟机: 59 二、 获取指定对象的定义: 59 三、 获取要调用的方法: 59 四、 调用JAVA方法: 60 五、 获得属性的定义: 60 六、 数组处理: 60 七、 异常: 60 八、 多线程调用 61 Java代码 61 命令行运行:javap -s -p MyTest ,输出: 62 C代码testjava.c: 62 编译: 65 运行结果: 65

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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