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无法实现,比如说涉及到底层驱 ...
随机推荐
- span和input同一行布局的时候,高度偏移解决方案
input标签或收盘标签 添加代码: vertical-align:top;
- MFC中的一般经验之谈4
MFC中的窗口控件,都是从CWnd类中继承的.MFC以及ResourceEditor支持的所有控件称为标准控件. 在对话框资源文件夹下,然后邮件新建添加新对话框,新建对话框后要在资源视图中的对话框文件 ...
- 在spark中启动standalone集群模式cluster问题
spark-submit --master spark://master:7077 --deploy-mode cluster --driver-cores 2 --driver-memory 100 ...
- struct timeval 计时问题
linux编程中,如果用到计时,可以用struct timeval获取系统时间.struct timeval的函数原型如下: struct timeval { __kernel_time_t tv_s ...
- 基于Extjs的web表单设计器
由于这样工作和自身的一些原因很长一段时间没有写过博客了.最近想把自己前面一段时间搞出的一个表单设计器的相关经验或者经历记录下来.分享给大家,也算是对自己前2个月的一个总结回顾吧. 首先介绍一下开发此版 ...
- .net core 使用 redis
.net core 使用 redis 个人感觉.net core 对于微软技术而言有很重要的意义 ,所以最近已有时间就想看一看关于.net core 的文章. 今天我就来写一写如何在.net core ...
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
一.简介 Spring Data MongoDB 项目提供与MongoDB文档数据库的集成.Spring Data MongoDB POJO的关键功能区域为中心的模型与MongoDB的DBColle ...
- django系列1--介绍与简单原理, wsgiref模块
一.web应用框架 Web应用框架(Web application framework)是一种计算机软件框架,用来支持动态网站.网络应用程序及网络服务的开发.这种框架有助于减轻网页开发时共通性活动的工 ...
- Application Loader上传app,一直卡在“正在通过 App Store 进行鉴定”
1.问题现象描述 上传iOS应用,卡在 Authenticating with the iTunes Store 2.解决办法 2.1 打开终端输入代码即可 cd ~ mv .itmstranspor ...
- Web Api 内部数据思考 和 利用http缓存优化 Api
在上篇<Web Api 端点设计 与 Oauth>后,接着我们思考Web Api 的内部数据: 其他文章:<API接口安全加强设计方法> 第一 实际使用应该返回怎样的数据 ? ...