C语言调用Java JNI

最近项目中需要使用JNI,所以研究了一下,其中遇到过不少问题,总结一下,让遇到同样问题的人可以得到解决。

在C/C++中调用Java的方法一般分为五个步骤:初始化虚拟机、获取类、获取类的方法、创建类对象、调用方法和退出虚拟机。

下面写一个小程序测试一下:

Java代码:

  1. package jni.test;  
  2.   
  3. public class Demo {  
  4.   
  5.     public static int COUNT = 8;  
  6.   
  7.     public String msg;  
  8.     private int[] counts;  
  9.   
  10.     public Demo() {  
  11.         this("缺省构造函数");  
  12.     }  
  13.   
  14.     public Demo(String msg) {  
  15.         System.out.println("<init>:" + msg);  
  16.         this.msg = msg;  
  17.         this.counts = null;  
  18.     }  
  19.   
  20.     public String getMessage() {  
  21.         return msg;  
  22.     }  
  23.   
  24.     public int[] getCounts() {  
  25.         return counts;  
  26.     }  
  27.   
  28.     public void setCounts(int[] counts) {  
  29.         this.counts = counts;  
  30.     }  
  31.   
  32.     public void throwExcp() throws IllegalAccessException {  
  33.         throw new IllegalAccessException("exception occur.");  
  34.     }  
  35. }  

上面的代码很好理解,我相信你能看的懂,我就不说了。

下面是C语言代码,里面有注释,这里先不详细说明,主要先跑起来再说:

  1. #include <stdio.h>  
  2. #include <jni.h>  
  3. #include <stdlib.h>  
  4. #include <iostream.h>  
  5. int main() {  
  6.     // 定义用到的变量  
  7.     int res;  
  8.     JavaVM *jvm;  
  9.     JNIEnv *env;  
  10.     JavaVMInitArgs vm_args;  
  11.     JavaVMOption options[3];  
  12.     vm_args.version;  
  13.       
  14.     // 设置初始化参数  
  15.     options[0].optionString = "-Djava.compiler=NONE";  
  16.     // classpath有多个时,用";"分隔,UNIX下以":"分割。  
  17.     options[1].optionString = "-Djava.class.path=.";  
  18.     // 用于跟踪运行时的信息  
  19.     options[2].optionString = "-verbose:jni";  
  20.     // 版本号设置不能漏  
  21.     vm_args.version = JNI_VERSION_1_6;  
  22.     vm_args.nOptions = 3;  
  23.     vm_args.options = options;  
  24.     vm_args.ignoreUnrecognized = JNI_TRUE;  
  25.     // 1.初始化虚拟机  
  26.     res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  
  27.     if (res < 0)  
  28.     {  
  29.         fprintf(stderr, "Can't create Java VM\n");  
  30.         exit(1);  
  31.     }  
  32.     // 2.获取类  
  33.     jclass cls = env->FindClass("jni/test/Demo");  
  34.     // 3.获取类的方法  
  35.     jmethodID mid= env->GetMethodID(cls,"getMessage","()Ljava/lang/String;");  
  36.     // 获取Java的构造方法  
  37.     jmethodID con=env->GetMethodID(cls,"<init>","(Ljava/lang/String;)V");  
  38.     jstring strinit = env->NewStringUTF("Still is coding!");  
  39.     jvalue arg[1];  
  40.     arg[0].l = strinit;  
  41.     //env->AllocObject(cls);  
  42.     // 4.创建类的对象  
  43.     jobject obj = env->NewObjectA(cls,con,arg);  
  44.     // 调用对象的方法  
  45.     jstring msg = (jstring)env-> CallObjectMethod(obj, mid);  
  46.       
  47.     cout<<msg<<endl;  
  48.     char *str=(char *)env->GetStringUTFChars(msg,JNI_FALSE);  
  49.     printf("%s===",str);  
  50.     // 5.退出虚拟机  
  51.     jvm->DestroyJavaVM();  
  52.     fprintf(stdout, "Java VM destory.\n");  
  53.     return 0;  
  54. }  

把以上C语言代码用VC6.0打开,然后编译,下面问题就来了,我们一个一个解决。

编译的时候首先会出现如下问题:

错误很明显,我们上面包含了jni.h,但是没找到。这是需要设置一下VC

Tools->Options->Directories,添加JDK安装目录下的两个目录,如图:

同时在Library files中添加JDK下面的LIB目录,如下图:

点击OK完成,重新编译。

好,新问题又来了,看下面描述:

也很明显,说明没有找到jvm.lib。继续设置VCProject->Settings->Link->Object/library modules中把上述路径替换为本机实际安装JDK中的jvm.lib目录,添加完后如下图:


点击OK后重新编译,呵呵,又来问题了,我很高兴啊。


这个问题在网上查了一下,原来是我JDK安装在Program Files下的问题,因为Program Files路径中有一个空格,真郁闷,没办法,只好重装JDK,注意安装目录中不能再有空格了。安装完了,按照上面出现的问题再重新设置一下VC,然后编译,没问题,运行,哇靠,又是一个问题:


这个问题可是花了我大半天时间才搞定的,但其实做法很简单。

看错描述,是没找到jvm.dll,网上很多人说直接找到这个文件把它拷贝到当前目录。但是这种方法不可取,因为jvm.dll这个东东还会依赖其他的文件的,而且它找其它所依赖的文件是通过相对路径找的,你直接就搞这么一个文件出来,其它的也找不到啊。所以这里有一个很好的解决方案,就是把D:\Java\jdk1.6.0_23\jre\bin\client这个JDK下的路径加入Path环境变量,加完之后记得重新用VC打开CPP文件,这个很重要,否则,这个问题还是没有解决。

点击编译,运行,如果出现如下画面,OK,恭喜你,C语言调用Java成功了,下面要做的就是去看代码,并且了解运行的机理了,这个我就不多说了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值