一、关于JNI

JNI( Java Native Interface )主要是实现Java和C/C++语言之间的通信。

Java通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使Java可以实现和本地机器的紧密联系,调用系统级的各接口方法。

二、实现步骤

(1)把Java中需要的调用的方法加上native关键字,封装到一个类里边。例如:

  1. //文件:Ctest.java
  2. public class Ctest{
  3. static
  4. {
  5. System.loadLibrary("myself");
  6. }
  7. public native void testJNI(); //声明
  8. public static void main(String[] args)
  9. {
  10. Ctest test=new Ctest ();
  11. test. testJNI ();
  12. }
  13. }

代码折叠

注意:全局类要用类名来定义文件名

(2)使用javac Ctest.java编译代码,生成对应的类文件Ctest.class。

(3)使用javah Ctest生成Ctest.h文件,javah后边跟的是类名字,.h文件里边就是使用jni规则定义的C语言与Java的接口。内容如下:

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class Ctest */
  4.  
  5. #ifndef _Included_Ctest
  6. #define _Included_Ctest
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /*
  11. * Class: Ctest
  12. * Method: testJNI
  13. * Signature: ()V
  14. */
  15. JNIEXPORT void JNICALL Java_Ctest_testJNI(JNIEnv *, jobject);
  16.  
  17. #ifdef __cplusplus
  18. }
  19. #endif
  20. #endif

代码折叠

(4)根据Ctest.h中函数的声明来实现函数的定义,编写xxx.c文件,把Ctest.h包含进去即可。

  1. #include <stdio.h>
  2. #include "Ctest.h"
  3. JNIEXPORT void JNICALL Java_Ctest_testJNI(JNIEnv *env, jobject obj)
  4. {
  5. printf("\ntesting jni .............\n");
  6. printf(".........................\n");
  7. }

代码折叠

(5)编译c文件,生成动态链接库.so文件

寻找jni.h和jni_md.h头文件路径:find / -name “*jni.h*”

Ubuntu12.04系统上:/usr/lib/jvm/java-6-openjdk-amd64/include/ 和

/usr/lib/jvm/java-6-openjdk-amd64/include/linux/

树莓派系统上:/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/include/ 和

/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/include/linux/

Makefile内容:

  1. libmyself.so:myself.o
  2. gcc -Wall -rdynamic -shared -o libmyself.so myself.o
  3. %.o:%.c
  4. gcc -I/usr/lib/jvm/jdk--oracle-arm-vfp-hflt/include/ -I/usr/lib/jvm/jdk--oracle-arm-vfp-hflt/include/linux/ -fPIC -c -o $@ $^
  5. clean:
  6. rm -rf *.o *.so

代码折叠

(6)测试结果:完成

三、问题解决

问1.什么是JDK?如何选择版本?

答1. (Java Development Kit) Java语言的软件开发工具包,主要用来编译Java程序;版本选择:

①SE(J2SE),standard edition,标准版,是我们通常用的一个版本,从JDK 5.0开始,改名为Java SE。

②EE(J2EE),enterprise edition,企业版,使用这种JDK开发J2EE应用程序,从JDK 5.0开始,改名为Java EE。

③ME(J2ME),micro edition,主要用于移动设备、嵌入式设备上的java应用程序,从JDK 5.0开始,改名为Java ME。

问2.JDK的组成有哪些?

答2. javac – 编译器,将源程序转成字节码

jar – 打包工具,将相关的类文件打包成一个文件

javadoc – 文档生成器,从源码注释中提取文档

jdb – debugger,查错工具

java – 运行编译后的java程序(.class后缀的)

appletviewer:小程序浏览器,一种执行HTML文件上的Java小程序的Java浏览器。

Javah:产生可以调用Java过程的C过程,或建立能被Java程序调用的C过程的头文件。

Javap:Java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义。

Jconsole: Java进行系统调试和监控的工具

问3.Java和C语言之间的基本数据类型是如何进行转换的?

答3.参考这篇博文http://blog.csdn.net/xyang81/article/details/42047899

问4.Java是如何读C的数组的?又是如何把值写到C语言的数组里?

答4.通过jni.h头文件中的函数来实现数据的传递。例如:

  1. //file:testJNI.java
  2. import java.util.Arrays;
  3. public class testJNI{
  4. static
  5. {
  6. System.loadLibrary("myself");
  7. }
  8. private byte[] mybuf;
  9.  
  10. public native void setBuffer(byte[] buffer,int len);
  11. public native byte[] getBuffer();
  12. public testJNI()
  13. {
  14. mybuf = new byte[30];
  15. }
  16. public static void main(String[] args)
  17. {
  18. int i;
  19. byte a;
  20. byte[] pbuf;
  21. a = 'e';
  22. testJNI test=new testJNI();
  23. for(i=0;i<10;i++)
  24. test.mybuf[i] = a;
  25. test.setBuffer(test.mybuf,10);
  26. pbuf = test.getBuffer();
  27. for(i=0; i<10; i++)
  28. System.out.print(pbuf[i]+",");
  29. System.out.print('\n');
  30. }
  31. }

testJNI.java代码折叠

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class testJNI */
  4.  
  5. #ifndef _Included_testJNI
  6. #define _Included_testJNI
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /*
  11. * Class: testJNI
  12. * Method: setBuffer
  13. * Signature: ([BI)V
  14. */
  15. JNIEXPORT void JNICALL Java_testJNI_setBuffer(JNIEnv *, jobject, jbyteArray, jint);
  16.  
  17. /*
  18. * Class: testJNI
  19. * Method: getBuffer
  20. * Signature: ()[B
  21. */
  22. JNIEXPORT jbyteArray JNICALL Java_testJNI_getBuffer(JNIEnv *, jobject);
  23.  
  24. #ifdef __cplusplus
  25. }
  26. #endif
  27. #endif

testJNI.java代码折叠

  1. #include <stdio.h>
  2. #include "testJNI.h"
  3.  
  4. JNIEXPORT void JNICALL Java_testJNI_setBuffer(JNIEnv *env, jobject obj, jbyteArray buffer, jint len)
  5. {
  6. int i;
  7. char table[30];
  8. char *ptab;
  9. printf("\ntesting jni array.............\n");
  10.  
  11. //这个函数是将java里的数组拷贝到C这边,执行完table获得java传过来的数组值
  12. (*env)->GetByteArrayRegion(env,buffer,0,len,table);
  13. for(i=0;i<len;i++)
  14. printf("table[%d]=%c,",i,table[i]);
  15. printf("\n");
  16. /*
  17. * 也可以使用这个函数,将本地的指针ptab直接指向Java端的数组地址,
  18. * 其实本质上是JVM在堆上分配的这个数组对象上增加一个引用计数,保证
  19. * 垃圾回收的时候不要释放,从而交给本地的指针使用,使用完毕后指针
  20. * 一定要记得通过ReleaseByteArrayElements进行释放,否则会产生内存泄露。
  21. */
  22. ptab = (*env)->GetByteArrayElements(env,buffer,0);
  23. if(ptab ==NULL)
  24. {
  25. printf("ReleaseByteArrayElements error.\n");
  26. return ;
  27. }
  28. for(i=0;i<len;i++)
  29. printf("ptab[%d]=%c,",i,ptab[i]);
  30. printf("\n");
  31. (*env)->ReleaseByteArrayElements(env,buffer,ptab,0);
  32. }
  33.  
  34. JNIEXPORT jbyteArray JNICALL Java_testJNI_getBuffer(JNIEnv *env, jobject obj)
  35. {
  36. int i;
  37. char buffer[30];
  38. for(i=0;i<10;i++)
  39. buffer[i] = 'a';
  40. // 在JNI层分配数组空间
  41. jbyteArray array = (*env)->NewByteArray(env,30);
  42. // 将buffer值复制给JNI层数组
  43. (*env)->SetByteArrayRegion(env,array,0,10,buffer);
  44. // 返回访问指针
  45. return array;
  46. // 此外还有一种方法可以实现,使用GetDirectBufferAddress()函数
  47. }

myself.c代码折叠

  1. libmyself.so:myself.o
  2. gcc -Wall -rdynamic -shared -o libmyself.so myself.o
  3.  
  4. %.o:%.c
  5. gcc -I/usr/lib/jvm/java--openjdk-amd64/include/ -I/usr/lib/jvm/java--openjdk-amd64/include/linux/ -fPIC -c -o $@ $^
  6.  
  7. clean:
  8. rm -rf *.o *.so

Makefile代码折叠

Java调用C函数的更多相关文章

  1. Android使用JNI(从java调用本地函数)

    当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...

  2. java调用matlab函数

    如何将实验结果在matlab中可视化呢,下面使用java语言编程,调用matlab中的函数: 本人安装的是Matlab7.11.0 (R2010a)和 Eclipse 4.2 : 1)首先设置环境变量 ...

  3. Java 调用 Javascript 函数的范例

    在Java 7 以后,可以在Java代码中调用javascript中的函数,请看下面的例子: package com.lee; import java.io.FileNotFoundException ...

  4. Linux平台下Java调用C函数

    JNI是Java native interface的简写,可以译作Java原生接口.Java可以通过JNI调用C/C++的库,这对于那些对性能要求比较高的Java程序无疑是一个 福音. 使用JNI也是 ...

  5. java调用js函数

    问题:js函数可能有多个,之间有相互调用关系,有jquery jar包 org.mozilla.javascript-1.7.2 js   envjs-1.2.js java代码 import jav ...

  6. java调用c++函数的简单笔记

    java使用jni调用c++动态库函数. 步骤: 1.编写java测试代码如下: public class CallNativeDemo { native void func(); native do ...

  7. java调用oracle函数

    /** * 调用函数取得数据表的ID值 * @param tableName 表名 * @return * @throws SQLException */ public String callFun( ...

  8. Android JNI之JAVA调用C/C++层

    转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5929996.html 一.java调用本地函数的开发步骤: 1.编写本地方法的类(可以说是用来叙述本地方法的类 ...

  9. JAVA调用c/c++代码

    JNI是Java Native Interface的缩写,中文为JAVA本地调用.使用JNI可以很方便的用我们的Java程序调用C/C++程序.很多时候,某些功能用Java无法实现,比如说涉及到底层驱 ...

随机推荐

  1. Class 'App\Http\Controllers\DB' not found and I also cannot use a new Model

    使用laravel的db插入数据 DB::table('tags')->insert( ['name'=>'test'] ); 报错Class 'App\Http\Controllers\ ...

  2. 利用Word发布文章到博客

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  3. What Are Tango Poses?Tango姿态是什么?

     What Are Tango Poses?什么是Tango姿态? As your device moves through 3D space, it calculates where it is ( ...

  4. 转载VC6.0 子窗口和父窗口

    这个是我周一在一家公司做的上机题中的一道,当场没做出来.我当时只跟考官说了设计思路,是带回来查了几本资料书之后才完成的.因为有半个学期没用VC开发了……,最近一直都在实践ASP.NET相关的…… 建立 ...

  5. PYTHON 和R的对比

    为了鼓励新工具的出现,机器学习和数据分析领域似乎已经成了“开源”的天下.Python 和 R 语言都具有健全的生态系统,其中包括了很多开源工具和资源库,从而能够帮助任何水平层级的数据科学家展示其分析工 ...

  6. 深海划水队项目--七天冲刺之day7

    站立式会议: 昨天已完成的工作:设置游戏按键,检查重合.检查是否超出边界.检查是否可以下落,方块的硬下落和软下落方法. 今日已完成的工作:添加方法:方块的着陆和消除. 工作中遇到的困难:在消除方块的时 ...

  7. Github 的注册教程和初步使用体验

    我叫许晴,是网工143的学生,学号是1413042064,兴趣包括手绘,看书和手游.学习过c++和汇编语言课程,但在编程方面没什么独立实践经验. 我的Githup用户名是 XQ123 .下面是我在gi ...

  8. selenium 元素可以定位到,但是无法点击问题

    报错1: selenium.common.exceptions.WebDriverException: Message: Element is not clickable at point (82, ...

  9. Angular4 配置问题

    出现错误: Local workspace file ('angular.json') could not be found.Error: Local workspace file ('angular ...

  10. cesium编程中级开篇

    cesium编程中级开篇 其实初级,中级并无定论,我理解的初级是根据官方教程,先学会如何部署环境,搭建hello world,使用官方提供的工具,完成一些示例, 而中级就是在这些的基础上,自己定制一些 ...