在C/C++中调用Java的方法一般分为五个步骤:初始化虚拟机、获取类、获取类的方法、创建类对象、调用方法和退出虚拟机。
    
   
    
     
      以下摘自:http://blog.csdn.net/sunchaoenter/article/details/6598719
     
    
   
    
    
   
Java代码:
- 
      
 
 package
 
 
 jni.test;
 
 
- 
      
 
- 
      
 
 public
 
 
 
 
 class
 
 
 Demo {
 
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 int
 
 
 COUNT =
 
 
 8
 
 
 ;
 
 
- 
      
 
- 
      
 
 public
 
 
 String msg;
 
 
- 
      
 
 private
 
 
 
 
 int
 
 
 [] counts;
 
 
- 
      
 
- 
      
 
 public
 
 
 Demo() {
 
 
- 
      
 
 this
 
 
 (
 
 
 “缺省构造函数”
 
 
 );
 
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 Demo(String msg) {
 
 
- 
      
 System.out.println(
 
 “<init>:”
 
 
 + msg);
 
 
- 
      
 
 this
 
 
 .msg = msg;
 
 
- 
      
 
 this
 
 
 .counts =
 
 
 null
 
 
 ;
 
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 String getMessage() {
 
 
- 
      
 
 return
 
 
 msg;
 
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 int
 
 
 [] getCounts() {
 
 
- 
      
 
 return
 
 
 counts;
 
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 void
 
 
 setCounts(
 
 
 int
 
 
 [] counts) {
 
 
- 
      
 
 this
 
 
 .counts = counts;
 
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 void
 
 
 throwExcp()
 
 
 throws
 
 
 IllegalAccessException {
 
 
- 
      
 
 throw
 
 
 
 
 new
 
 
 IllegalAccessException(
 
 
 “exception occur.”
 
 
 );
 
 
- 
      
 }
 
- 
      
 }
 
上面的代码很好理解,我相信你能看的懂,我就不说了。
下面是C语言代码,里面有注释,这里先不详细说明,主要先跑起来再说:
- 
      
 
 #include <stdio.h>
 
 
 
 
- 
      
 
 #include <jni.h>
 
 
 
 
- 
      
 
 #include <stdlib.h>
 
 
 
 
- 
      
 
 #include <iostream.h>
 
 
 
 
- 
      
 
 int
 
 
 main() {
 
 
- 
      
 
 // 定义用到的变量
 
 
 
 
- 
      
 
 int
 
 
 res;
 
 
- 
      
 JavaVM *jvm;
 
- 
      
 JNIEnv *env;
 
- 
      
 JavaVMInitArgs vm_args;
 
- 
      
 JavaVMOption options[3];
 
- 
      
 vm_args.version;
 
- 
      
 
- 
      
 
 // 设置初始化参数
 
 
 
 
- 
      
 options[0].optionString =
 
 “-Djava.compiler=NONE”
 
 
 ;
 
 
- 
      
 
 // classpath有多个时,用”;”分隔,UNIX下以”:”分割。
 
 
 
 
- 
      
 options[1].optionString =
 
 “-Djava.class.path=.”
 
 
 ;
 
 
- 
      
 
 // 用于跟踪运行时的信息
 
 
 
 
- 
      
 options[2].optionString =
 
 “-verbose:jni”
 
 
 ;
 
 
- 
      
 
 // 版本号设置不能漏
 
 
 
 
- 
      
 vm_args.version = JNI_VERSION_1_6;
 
- 
      
 vm_args.nOptions = 3;
 
- 
      
 vm_args.options = options;
 
- 
      
 vm_args.ignoreUnrecognized = JNI_TRUE;
 
- 
      
 
 // 1.初始化虚拟机
 
 
 
 
- 
      
 res = JNI_CreateJavaVM(&jvm, (
 
 void
 
 
 **)&env, &vm_args);
 
 
- 
      
 
 if
 
 
 (res < 0)
 
 
- 
      
 {
 
- 
      
 fprintf(stderr,
 
 “Can’t create Java VM\n”
 
 
 );
 
 
- 
      
 exit(1);
 
- 
      
 }
 
- 
      
 
 // 2.获取类
 
 
 
 
- 
      
 jclass cls = env->FindClass(
 
 “jni/test/Demo”
 
 
 );
 
 
- 
      
 
 // 3.获取类的方法
 
 
 
 
- 
      
 jmethodID mid= env->GetMethodID(cls,
 
 “getMessage”
 
 
 ,
 
 
 “()Ljava/lang/String;”
 
 
 );
 
 
- 
      
 
 // 获取Java的构造方法
 
 
 
 
- 
      
 jmethodID con=env->GetMethodID(cls,
 
 “<init>”
 
 
 ,
 
 
 “(Ljava/lang/String;)V”
 
 
 );
 
 
- 
      
 jstring strinit = env->NewStringUTF(
 
 “Still is coding!”
 
 
 );
 
 
- 
      
 jvalue arg[1];
 
- 
      
 arg[0].l = strinit;
 
- 
      
 
 //env->AllocObject(cls);
 
 
 
 
- 
      
 
 // 4.创建类的对象
 
 
 
 
- 
      
 jobject obj = env->NewObjectA(cls,con,arg);
 
- 
      
 
 // 调用对象的方法
 
 
 
 
- 
      
 jstring msg = (jstring)env-> CallObjectMethod(obj, mid);
 
- 
      
 
- 
      
 cout<<msg<<endl;
 
- 
      
 
 char
 
 
 *str=(
 
 
 char
 
 
 *)env->GetStringUTFChars(msg,JNI_FALSE);
 
 
- 
      
 printf(
 
 “%s===”
 
 
 ,str);
 
 
- 
      
 
 // 5.退出虚拟机
 
 
 
 
- 
      
 jvm->DestroyJavaVM();
 
- 
      
 fprintf(stdout,
 
 “Java VM destory.\n”
 
 
 );
 
 
- 
      
 
 return
 
 
 0;
 
 
- 
      
 }
 
把以上C语言代码用VC6.0打开,然后编译,下面问题就来了,我们一个一个解决。
编译的时候首先会出现如下问题:
   
    错误很明显,我们上面包含了jni.h
    
     ,但是没找到。这是需要设置一下
    
    
     VC
    
    
     。
    
   
    Tools->Options->Directories,
    
     添加
    
    
     JDK
    
    
     安装目录下的两个目录,如图:
    
   
   
    同时在
    
     Library files
    
    
     中添加
    
    
     JDK
    
    
     下面的
    
    
     LIB
    
    
     目录,如下图:
    
   
   
    点击
    
     OK
    
    
     完成,重新编译。
    
   
好,新问题又来了,看下面描述:
   
    也很明显,说明没有找到
    
     jvm.lib
    
    
     。继续设置
    
    
     VC
    
    
     ,
    
    
     Project->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
    
    
     成功了,下面要做的就是去看代码,并且了解运行的机理了,这个我就不多说了。
    
   
     
   
    
     
    
   
    
     java 调用 c/c++
    
   
    
     1.使用native定义方法 本地方法
    
   
    
     
      2.编译得到字节码文件
     
    
   
    
     
      3.使用javah -jni xxx命令生成C语言头文件
     
    
   
    
     
      4.C语言实现头文件定义的方法,再用ndk打包城.so文件
     
    
   
    
     
      5.java程序中使用loadlibry方法加载库文件
     
    
   
    
     
      
     
    
   
    
     
      问题找不到文件:
     
    
   
    
     
     
    
   
    
     
      使用Javah 可以获取您的 Java 源文件并生成 C/C++头文件,其中包含您的 Java 代码中所有本地方法(native方法)的 JNI 存根(stub,C头文件)。如果您正在生成一个类的 JNI 存根,而且您已经把这个类定义为包的一部分,那么您 必须指定完全限定的类名。
     
    
   
    
     下面举例说明:
    
   
    
     使用eclipse建立一个工程假设工程路径为$ProjectPath,并且你已经定义了一个类,并且带包名:cn.com.comit.jni
    
   
    
     —————————-
    
   
| 
          1
          
          2
          
          3
          
          4
          
          5
          
          6
          
          7
          
          8
          
          9
          
          10
          
          11
          
          12
          
          13
          
          14
          
          15
          
          16
          
          17
          
          18
          |  | 
    
     —————————-
    
   
    
     eclipse会自动帮你编译出一个字节码文件HelloJni.class,路径是$ProjectPath\bin\cn\com\comit\jni,很可能你会先cd到.class的目录这么做:
    
   
    
     >
     
      cd $ProjectPath\bin\cn\com\comit\jni
     
    
   
    
     >$ProjectPath\bin
     
      javah HelloJni
     
    
   
    
     发现执行出错:
    
   
    
     错误:无法访问 HelloJni
     
     错误的类文件: .\HelloJni.class
     
     类文件包含错误的类: cn.com.comit.jni.HelloJni
     
     请删除该文件或确保该文件位于正确的类路径子目录中。
    
   
    
     看来是路径有问题咯。那改成
    
   
    
     javah cn.com.comit.jni.HelloJni
    
   
    
     再次运行,发现还是错误:
    
   
    
     错误:无法访问 cn.com.comit.jni.HelloJni
     
     未找到 cn.com.comit.jni.HelloJni 的类文件
     
     javadoc: 错误 – 找不到类 cn.com.comit.jni.HelloJni。
    
   
    
     
    
   
    
     
    
   
    
     
      如果是android工程需要用户切换的目录为
      
       $ProjectPath\bin\classes\文件夹
      
     
    
   
    
     怎么才能解决这个问题呢?其实只要cd到包的上一级目录(我们这里是$ProjectPath\bin)在运行下面的命令就搞定了:
    
   
    
     javah -classpath . cn.com.comit.jni.HelloJni
    
   
    
     看一下生成的C头文件:
    
   
| 
          1
          
          2
          
          3
          
          4
          
          5
          |  | 
| 
          1
          
          2
          |  | 
| 
          1
          |  | 
| 
          1
          
          2
          
          3
          
          4
          
          5
          
          6
          
          7
          
          8
          
          9
          
          10
          
          11
          
          12
          
          13
          
          14
          
          15
          |  | 
    
     android.mk文件的简介:
    
   
    
     http://www.cnblogs.com/luxiaofeng54/archive/2011/08/13/2137577.html
     
    
   
 
