由于JNI调用C和调用C++差不多,而且C++中可以混合写C代码,所以这里主要是写关于JNI调用C++的部分。

  • 一般步骤:

  1. 先是写普通的Java类,其中包括本地方法调用。 
  2. 然后编译这个Java类,调用javah命令,生成.h头文件
  3. 接着,就是实现头文件中的函数;实现过程中有点比较麻烦,要知道JNI中JAVA和C/C++的类型转换,比如数组类型的转换,基本类型的转换等,最好是看文档,或者网上找相关资料。

源代码链接:http://files.cnblogs.com/GDUT/jni-demo.rar

  • JNI的调用效果图:

  • 下面是调用JNI的具体过程:

1.  普通Java类(包含测试方法):MyJNI.java

 public class MyJNI {

     //加载动态链接库
     static {
         System.out.println("开始加载动态链接库");
         System.loadLibrary("MyJNI");
         System.out.println("动态链接库加载完毕。");
     }

     public native void go();

     public native void run();

     public native String getName();

     public native int[] sort(int[] array);

     //测试
     public static void main(String[] args) {
         MyJNI jni = new MyJNI();
         int[] array = {5, 3, 6, 35, 74, 8}, sortedArray;

         jni.run();
         jni.go();
         jni.getName();
         sortedArray = jni.sort(array);
         //由于这是本地方法调用,这里的数组和平常的数组的引用不太一样。

         for(int i=0; i<sortedArray.length; i++){
             System.out.print(sortedArray[i] + "\t");
         }

     }
 }

2.  由Java类编译后生成的C++头文件:MyJNI.h

 /* DO NOT EDIT THIS FILE - it is machine generated */
 #include <jni.h>
 /* Header for class MyJNI */

 #ifndef _Included_MyJNI
 #define _Included_MyJNI
 #ifdef __cplusplus
 extern "C" {
 #endif
 /*
  * Class:     MyJNI
  * Method:    go
  * Signature: ()V
  */
 JNIEXPORT void JNICALL Java_MyJNI_go
   (JNIEnv *, jobject);

 /*
  * Class:     MyJNI
  * Method:    run
  * Signature: ()V
  */
 JNIEXPORT void JNICALL Java_MyJNI_run
   (JNIEnv *, jobject);

 /*
  * Class:     MyJNI
  * Method:    getName
  * Signature: ()Ljava/lang/String;
  */
 JNIEXPORT jstring JNICALL Java_MyJNI_getName
   (JNIEnv *, jobject);

 /*
  * Class:     MyJNI
  * Method:    sort
  * Signature: ([I)[I
  */
 JNIEXPORT jintArray JNICALL Java_MyJNI_sort
   (JNIEnv *, jobject, jintArray);

 #ifdef __cplusplus
 }
 #endif
 #endif

3.  需要调用的C++函数的相关文件:MyJNIImpl.cpp

 #include <jni.h>
 #include "MyJNI.h"
 #include <stdio.h>

 /*
  * Class:     MyJNI
  * Method:    go
  * Signature: ()V
  */
 JNIEXPORT void JNICALL Java_MyJNI_go
   (JNIEnv * env, jobject jobj){

     printf("I am going....\n");
 }

 /*
  * Class:     MyJNI
  * Method:    run
  * Signature: ()V
  */
 JNIEXPORT void JNICALL Java_MyJNI_run
   (JNIEnv * env, jobject jobj){

     printf("I am running....\n");
 }

 /*
  * Class:     MyJNI
  * Method:    getName
  * Signature: ()Ljava/lang/String;
  */
 JNIEXPORT jstring JNICALL Java_MyJNI_getName
   (JNIEnv * env, jobject job){

    printf("I am GDUTtiantian, go with me.\n");
    //将字符串转化为jstring类型
    //jstring就是对应java的String类型
    jstring p = env->NewStringUTF("GDUTtiantian");
    return p;
 }

 /*
  * Class:     MyJNI
  * Method:    sort
  * Signature: ([I)[I
  */
 JNIEXPORT jintArray JNICALL Java_MyJNI_sort
   (JNIEnv * env, jobject jobj, jintArray array){

 jint* arr;//定义一个整形指针
     ;
     //对于整形数组的处理,主要有GetIntArrayElements与GetIntArrayRegion
     //第一种方法
     arr = env->GetIntArrayElements(array, NULL);//得到一个指向原始数据类型内容的指针
     jint length = env->GetArrayLength(array);//得到数组的长度

     ; i<length; i++){
         ; j<length; j++){
             if(arr[i] > arr[j]){
                 jint temp = arr[i];
                 arr[i] = arr[j];
                 arr[j] = temp;
             }
         }
     }

     ; i<length; i++){
         printf("%d ", arr[i]);
     }

     printf("\n排序完成\n");

     jintArray javaArray = env->NewIntArray(length);
     env->SetIntArrayRegion(javaArray, , length, arr);

     return javaArray;//返回排序后的数组
 }

编译之后,生成一个动态链接库文件:MyJNI.dll

在Java类中就是通过加载这个库文件,调用其中的相关函数。

调用的相关命令:

  • javac *.java
  • javah MyJNI
  • set JAVA_HOME=D:\SoftwareDeveloping\jdk32bit_1.6
  • g++ -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o MyJNI.dll MyJNIImpl.cpp
  • java MyJNI
  • 在操作过程中可能会出现的异常:

  1.  第一个异常 
 C:\Users\Administrator\Desktop>java HelloJNI
 Exception in thread "main" java.lang.UnsupportedClassVersionError: HelloJNI : Unsupported major.minor version 51.0
         at java.lang.ClassLoader.defineClass1(Native Method)
         at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
         at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
         at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
         at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
         at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
         at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
         at java.security.AccessController.doPrivileged(Native Method)
         at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
         at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
         at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
         at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
 Could not find the main class: HelloJNI.  Program will exit.

这个是JAVA虚拟机的版本低于编译器的问题,如果你用一个编译编译之后,然后把.class文件移动到另一个环境下执行,可能会出现这个问题。

  2.     第二个异常

 C:\Users\Administrator\Desktop>javac *.java

 C:\Users\Administrator\Desktop>java HelloJNI
 Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Administrator\Desktop\hello.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
         at java.lang.ClassLoader$NativeLibrary.load(Native Method)
         at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1807)
         at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1732)
         at java.lang.Runtime.loadLibrary0(Runtime.java:823)
         at java.lang.System.loadLibrary(System.java:1028)
         at HelloJNI.<clinit>(HelloJNI.java:3)
 Could not find the main class: HelloJNI.  Program will exit.

动态链接库.dll是32位,而JVM是64位,不匹配;可以安装一个32位的JVM;或者在64位环境下重新编译一个新的.dll文件。

3.    第三个异常

 C:\Users\Administrator\Desktop\jni>g++ -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o MyJNI.dll MyJNIImpl.cpp
 In file included from MyJNIImpl.cpp:1:
 MyJNI.h:2:17: jni.h: No such file or directory
 In file included from MyJNIImpl.cpp:1:
 MyJNI.h:15: error: expected constructor, destructor, or type conversion before "void"
 MyJNI.h:15: error: expected `,' or `;' before "void"
 MyJNI.h:23: error: expected constructor, destructor, or type conversion before "void"
 MyJNI.h:23: error: expected `,' or `;' before "void"
 MyJNI.h:31: error: `JNIEXPORT' does not name a type
 MyJNI.h:39: error: `JNIEXPORT' does not name a type
 MyJNIImpl.cpp:10: error: expected constructor, destructor, or type conversion before "void"
 MyJNIImpl.cpp:10: error: expected `,' or `;' before "void"
 MyJNIImpl.cpp:21: error: expected constructor, destructor, or type conversion before "void"
 MyJNIImpl.cpp:21: error: expected `,' or `;' before "void"
 MyJNIImpl.cpp:32: error: `JNIEXPORT' does not name a type
 MyJNIImpl.cpp:47: error: `JNIEXPORT' does not name a type

这个报错主要是找不到jni.h文件,一般的原因:JAVA_HOME的路径有问题,注意这个路径是安装路径。用命令设置下,如果设置还是报这个错误,那么就到环境变量那里修改。

参考资料:http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html

JNI类型转换:http://www.cnblogs.com/lgydqy/archive/2012/02/28/2371592.html

函数

Java 数组类型

本地类型

GetBooleanArrayElements

jbooleanArray

jboolean

GetByteArrayElements

jbyteArray

jbyte

GetCharArrayElements

jcharArray

jchar

GetShortArrayElements

jshortArray

jshort

GetIntArrayElements

jintArray

jint

GetLongArrayElements

jlongArray

jlong

GetFloatArrayElements

jfloatArray

jfloat

GetDoubleArrayElements

jdoubleArray

jdouble

欢迎讨论交流, 我的主页:http://www.cnblogs.com/GDUT/

我的邮箱:zone.technology.exchange@gmail.com

JAVA的JNI调用的更多相关文章

  1. JAVA使用JNI调用C++动态链接库

    JAVA使用JNI调用C++动态链接库 使用JNI连接DLL动态链接库,并调用其中的函数 首先 C++中写好相关函数,文件名为test.cpp,使用g++编译为DLL文件,指令如下: g++ -sha ...

  2. Java通过JNI调用dll详细过程(转)

    源:Java通过JNI调用dll详细过程 最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无 ...

  3. ubuntu下Java通过JNI调用C

    下面看一个实例,如下: public class TestJNI { static { System.loadLibrary("diaoyong"); // 程序在加载时,自动加载 ...

  4. Java通过JNI调用C

    Java调用C有多种方式,本文介绍笔者最近的学习过程,避免今后再犯类似的错误. 首先,Java肯定是调用C的动态链接库,即通过编译器编译后的dll/so文件. 下面介绍gcc编译dll的方法. 一般情 ...

  5. Cocos2d-x java 通过jni调用c++的方法

    前面博客说到,cocos2d-x c++界面层运行在一个GLThread线程里面,严格的说是运行在Cocos2dxGLSurfaceView(继承自GLSurfaceView) 里面.opengl的渲 ...

  6. 关于Java通过JNI调用C 动态链接库(DLL)

    JNI介绍 用JNI实现Java和C语言的数据传递 JNI原理分析和详细步骤截图说明 jni的JNIEnv指针和jobject指针 JNI实现回调| JNI调用JAVA函数|参数和返回值的格式 Jni ...

  7. Java通过jni调用动态链接库

    (1)JNI简介 JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++).从Java1.1开始,JNI标准成为java ...

  8. 第39篇-Java通过JNI调用C/C++函数

    在某些情况下,Java语言需要通过调用C/C++函数来实现某些功能,因为Java有时候对这些功能显的无能为力,如想使用X86_64 的 SIMD 指令提升一下业务方法中关键代码的性能,又或者想要获取某 ...

  9. Java通过JNI调用C/C++

    From:http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与 ...

随机推荐

  1. Java web--反射(解刨)

    本质:先加载类           再解刨类的方法,字段,构造函数 目的:解刨出构造函数       为了new对象 解刨出字段             为了封装数据进去 解刨方法           ...

  2. mysql之预处理语句prepare、execute、deallocate

    预制语句的SQL语法基于三个SQL语句: PREPARE stmt_name FROM preparable_stmt; EXECUTE stmt_name [USING @var_name [, @ ...

  3. C语言中的union

    1.union中可以定义多个成员,union的大小由最大的成员的大小决定. 2.union成员共享同一块大小的内存,一次只能使用其中的一个成员,与struct形成鲜明对比. 3.对某一个成员赋值,会覆 ...

  4. arpg网页游戏之地图(三)

    地图分块加载类MapEngine,主要包含以下属性: g 地图层graphics,地图将画在上面 buffPixelRange 地图加载范围矩形 viewPort 屏幕视窗 currZoneArr 已 ...

  5. 加密和ssl机制细节

    1.1 背景知识 对称加密:加密解密使用同一密钥,加解密速度快.随着人数增多,密钥数量急增n(n-1)/2 非对称加密:使用公私钥配对加解密,速度慢.公钥是从私钥中提取出来的,一般拿对方公钥加密来保证 ...

  6. 一个很酷的加载loading效果--IT蓝豹

    一个很酷的加载loading效果,自定义LeafLoadingView实现,LeafLoadingView继承view, 本例子主要由以下几点构成 (1):RotateAnimation实现叶子旋转 ...

  7. js中的单体对象

  8. Razor引擎中的_ViewStart.cshtml

    Startup Code是在所有View执行之前加载和执行的代码. 在Razor引擎中的_ViewStart.cshtml 就是装载这些“预执行代码”的文件,它有两个特点: 一.就是所有View执行之 ...

  9. protobuff 配合 libevent 在Linux 和windows 下的使用

    protobuff 配合 libevent 在Linux 和windows 下的使用待补全. libprotobuf.lib libproto-lite.lib libprotoc.lib

  10. LightOJ 1094 - Farthest Nodes in a Tree(树的直径)

    http://acm.hust.edu.cn/vjudge/contest/121398#problem/H 不是特别理解,今天第一次碰到这种问题.给个链接看大神的解释吧 http://www.cnb ...