Java调用C函数
一、关于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函数的更多相关文章
- Android使用JNI(从java调用本地函数)
当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...
- java调用matlab函数
如何将实验结果在matlab中可视化呢,下面使用java语言编程,调用matlab中的函数: 本人安装的是Matlab7.11.0 (R2010a)和 Eclipse 4.2 : 1)首先设置环境变量 ...
- Java 调用 Javascript 函数的范例
在Java 7 以后,可以在Java代码中调用javascript中的函数,请看下面的例子: package com.lee; import java.io.FileNotFoundException ...
- Linux平台下Java调用C函数
JNI是Java native interface的简写,可以译作Java原生接口.Java可以通过JNI调用C/C++的库,这对于那些对性能要求比较高的Java程序无疑是一个 福音. 使用JNI也是 ...
- java调用js函数
问题:js函数可能有多个,之间有相互调用关系,有jquery jar包 org.mozilla.javascript-1.7.2 js envjs-1.2.js java代码 import jav ...
- java调用c++函数的简单笔记
java使用jni调用c++动态库函数. 步骤: 1.编写java测试代码如下: public class CallNativeDemo { native void func(); native do ...
- java调用oracle函数
/** * 调用函数取得数据表的ID值 * @param tableName 表名 * @return * @throws SQLException */ public String callFun( ...
- Android JNI之JAVA调用C/C++层
转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5929996.html 一.java调用本地函数的开发步骤: 1.编写本地方法的类(可以说是用来叙述本地方法的类 ...
- JAVA调用c/c++代码
JNI是Java Native Interface的缩写,中文为JAVA本地调用.使用JNI可以很方便的用我们的Java程序调用C/C++程序.很多时候,某些功能用Java无法实现,比如说涉及到底层驱 ...
随机推荐
- 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\ ...
- 利用Word发布文章到博客
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- What Are Tango Poses?Tango姿态是什么?
What Are Tango Poses?什么是Tango姿态? As your device moves through 3D space, it calculates where it is ( ...
- 转载VC6.0 子窗口和父窗口
这个是我周一在一家公司做的上机题中的一道,当场没做出来.我当时只跟考官说了设计思路,是带回来查了几本资料书之后才完成的.因为有半个学期没用VC开发了……,最近一直都在实践ASP.NET相关的…… 建立 ...
- PYTHON 和R的对比
为了鼓励新工具的出现,机器学习和数据分析领域似乎已经成了“开源”的天下.Python 和 R 语言都具有健全的生态系统,其中包括了很多开源工具和资源库,从而能够帮助任何水平层级的数据科学家展示其分析工 ...
- 深海划水队项目--七天冲刺之day7
站立式会议: 昨天已完成的工作:设置游戏按键,检查重合.检查是否超出边界.检查是否可以下落,方块的硬下落和软下落方法. 今日已完成的工作:添加方法:方块的着陆和消除. 工作中遇到的困难:在消除方块的时 ...
- Github 的注册教程和初步使用体验
我叫许晴,是网工143的学生,学号是1413042064,兴趣包括手绘,看书和手游.学习过c++和汇编语言课程,但在编程方面没什么独立实践经验. 我的Githup用户名是 XQ123 .下面是我在gi ...
- selenium 元素可以定位到,但是无法点击问题
报错1: selenium.common.exceptions.WebDriverException: Message: Element is not clickable at point (82, ...
- Angular4 配置问题
出现错误: Local workspace file ('angular.json') could not be found.Error: Local workspace file ('angular ...
- cesium编程中级开篇
cesium编程中级开篇 其实初级,中级并无定论,我理解的初级是根据官方教程,先学会如何部署环境,搭建hello world,使用官方提供的工具,完成一些示例, 而中级就是在这些的基础上,自己定制一些 ...