一、关于JNI

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

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

二、实现步骤

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

 //文件:Ctest.java
public class Ctest{
static
{
System.loadLibrary("myself");
}
public native void testJNI(); //声明
public static void main(String[] args)
{
Ctest test=new Ctest ();
test. testJNI ();
}
}

代码折叠

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

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

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

 /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Ctest */ #ifndef _Included_Ctest
#define _Included_Ctest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Ctest
* Method: testJNI
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_Ctest_testJNI(JNIEnv *, jobject); #ifdef __cplusplus
}
#endif
#endif

代码折叠

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

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

代码折叠

(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内容:

 libmyself.so:myself.o
gcc -Wall -rdynamic -shared -o libmyself.so myself.o
%.o:%.c
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 $@ $^
clean:
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头文件中的函数来实现数据的传递。例如:

 //file:testJNI.java
import java.util.Arrays;
public class testJNI{
static
{
System.loadLibrary("myself");
}
private byte[] mybuf; public native void setBuffer(byte[] buffer,int len);
public native byte[] getBuffer();
public testJNI()
{
mybuf = new byte[30];
}
public static void main(String[] args)
{
int i;
byte a;
byte[] pbuf;
a = 'e';
testJNI test=new testJNI();
for(i=0;i<10;i++)
test.mybuf[i] = a;
test.setBuffer(test.mybuf,10);
pbuf = test.getBuffer();
for(i=0; i<10; i++)
System.out.print(pbuf[i]+",");
System.out.print('\n');
}
}

testJNI.java代码折叠

 /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class testJNI */ #ifndef _Included_testJNI
#define _Included_testJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: testJNI
* Method: setBuffer
* Signature: ([BI)V
*/
JNIEXPORT void JNICALL Java_testJNI_setBuffer(JNIEnv *, jobject, jbyteArray, jint); /*
* Class: testJNI
* Method: getBuffer
* Signature: ()[B
*/
JNIEXPORT jbyteArray JNICALL Java_testJNI_getBuffer(JNIEnv *, jobject); #ifdef __cplusplus
}
#endif
#endif

testJNI.java代码折叠

 #include <stdio.h>
#include "testJNI.h" JNIEXPORT void JNICALL Java_testJNI_setBuffer(JNIEnv *env, jobject obj, jbyteArray buffer, jint len)
{
int i;
char table[30];
char *ptab;
printf("\ntesting jni array.............\n"); //这个函数是将java里的数组拷贝到C这边,执行完table获得java传过来的数组值
(*env)->GetByteArrayRegion(env,buffer,0,len,table);
for(i=0;i<len;i++)
printf("table[%d]=%c,",i,table[i]);
printf("\n");
/*
* 也可以使用这个函数,将本地的指针ptab直接指向Java端的数组地址,
* 其实本质上是JVM在堆上分配的这个数组对象上增加一个引用计数,保证
* 垃圾回收的时候不要释放,从而交给本地的指针使用,使用完毕后指针
* 一定要记得通过ReleaseByteArrayElements进行释放,否则会产生内存泄露。
*/
ptab = (*env)->GetByteArrayElements(env,buffer,0);
if(ptab ==NULL)
{
printf("ReleaseByteArrayElements error.\n");
return ;
}
for(i=0;i<len;i++)
printf("ptab[%d]=%c,",i,ptab[i]);
printf("\n");
(*env)->ReleaseByteArrayElements(env,buffer,ptab,0);
} JNIEXPORT jbyteArray JNICALL Java_testJNI_getBuffer(JNIEnv *env, jobject obj)
{
int i;
char buffer[30];
for(i=0;i<10;i++)
buffer[i] = 'a';
// 在JNI层分配数组空间
jbyteArray array = (*env)->NewByteArray(env,30);
// 将buffer值复制给JNI层数组
(*env)->SetByteArrayRegion(env,array,0,10,buffer);
// 返回访问指针
return array;
// 此外还有一种方法可以实现,使用GetDirectBufferAddress()函数
}

myself.c代码折叠

 libmyself.so:myself.o
gcc -Wall -rdynamic -shared -o libmyself.so myself.o %.o:%.c
gcc -I/usr/lib/jvm/java--openjdk-amd64/include/ -I/usr/lib/jvm/java--openjdk-amd64/include/linux/ -fPIC -c -o $@ $^ clean:
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. (转)centos liveCD liveDVD netinstall minimal DVD1 DVD2 版本区别

    LiveCD 和 LiveDVD 是可以直接光盘运行系统,但不能安装,两者差别在于容量大小,dvd包含的软件要多一些. netinstall 是用于网络安装和系统救援的镜像文件. minimal 这个 ...

  2. [label][paypal] Paypal 支付页面的语言显示问题

    答复 Frank 通过 Email2014-11-12 02:01 上午 您好 感谢您联系PayPal商家技术支持中心. PayPal登陆页面的语言是PayPal服务器根据以下各种因素来自动判断的:1 ...

  3. Android-自定义控件之事件分发

    最大范围 外层蓝色区域是继承ViewGroup 中间红色区域,也是继承ViewGroup 最中间黑色区域,是继承View 布局相关的代码: <!-- 事件分发 --> <view.c ...

  4. 20145233计算机病毒实践九之IDA的使用

    20145233计算机病毒实践之IDA的使用 PSLIST导出函数做了什么 这个函数是一个export函数,所以在view中选择export 查到后,双击打开这个函数的位置 仔细看这个函数可以发现这个 ...

  5. SqlerMonitor-复制

    在复制系统中因为一些配置上失误和人为的失误操作导致复制堵塞,Sqler Monitor 新增加了分析复制延迟邮件,配合复制错误监控邮件和延迟邮件,和复制元数据采集 可以在第一时间准确定位到问题,适合大 ...

  6. mysql 主从日志文件mysql-bin文件清除方法

    默认情况下mysql会一直保留mysql-bin文件,这样到一定时候,磁盘可能会被撑满,这时候是否可以删除这些文件呢,是否可以安全删除,是个问题,不建议使用rm命令删除,这样有可能会不安全,正确的方法 ...

  7. R语言中Fisher判别的使用方法

    最近编写了Fisher判别的相关代码时,需要与已有软件比照结果以确定自己代码的正确性,于是找到了安装方便且免费的R.这里把R中进行Fisher判别的方法记录下来. 1. 判别分析与Fisher判别 不 ...

  8. [Java]java内存及数据区

    Java运行时的数据区包括:(其中前两个是线程共享的) 1.方法区(Method Area) 存储已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据 2.堆(Heap) 存放对象实例 ...

  9. 网络正常只有自己访问网站异常一度让你怀疑,是不是被黑了!域名解析异常是如何发生的,如何解决处理及C#编程实现一键修改Hosts文件

    首先大家要知道在浏览器上浏览虚拟主机,必须使用Hosts文件或域名系统(DNS)实现主机名到IP地址的解析.在局域网中用Hosts文件或DNS都可以,在Internet上只能用DNS了. 1.当用户输 ...

  10. C# BackgroundWorker 的使用、封装

    示例代码: PT_USER_INFO user = new PT_USER_INFO(); IList<TES_COMBAT_TASK> taskList = new List<TE ...