当前位置: 首页 > news >正文

Java JNI介绍

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Java jni本意是Java native interface(Java本地接口),是为了方便Java调用c、c++等本地代码所封

装的一层接口。大家都知道,Java的优点是跨平台,但是作为优点的同时,其在本地交互的时候就编程了缺点。

Java的跨平台特性导致其本地交互的能力不够强大,一些和操作系统相关的特性Java无法完成,于是Java提供了

jni专门用于和本地代码交互,这样就增强了Java语言的本地交互能力。

通过Java jni,用户可以调用用c、c++所编写的native code。在html5视频的开发中就采用了jni,

android只用于ui的显示,其业务逻辑都是通过native code所完成的,android代码只是负责通过jni和native进

行交互。

通过Java jni来调用native code,需要如下几个步骤:

1.声明native接口函数,语法如下:public native static void set(int i);

其中native是Java的关键字,被native修饰的函数都是本地函数的接口,其具体功能要被native code来

实现。
//testdll.java
public class testdll
{
static
{
System.loadLibrary("my");
}
public native static int get();
public native static void set(int i);
public static void main(String[] args)
{
testdll test = new testdll();
test.set(3721);
System.out.println(test.get());
}
}

2.用javah命令导出Java jni中定义的本地方法的声明,这个是.h格式的头文件
首先用javac编译出class文件,然后在用javah导出头文件,我们发现导出的头文件,其函数声明发生了

变化,其中jint是jni定义的用来和c/c++交互的数据类型,可以当作int来用。

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

#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     testdll
 * Method:    get
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_testdll_get
  (JNIEnv *, jclass);

/*
 * Class:     testdll
 * Method:    set
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_testdll_set
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif
3. 实现Java jni中定义的native methods
有了头文件以后,就可以用本地函数去实现头文件中声明的native函数了,通常用c和c++来实现native

函数。
//my.c
#include "jni.h"
#include "testdll.h"
#include<stdio.h>

static int i;

JNIEXPORT jint JNICALL Java_testdll_get(JNIEnv *a, jclass b)
{
return i;
}

JNIEXPORT void JNICALL Java_testdll_set(JNIEnv *a, jclass b, jint j)
{
FILE *f;
f=fopen("my.txt","a+");
fwrite("嘿嘿你好啊xixi",1,14,f);
fclose(f);
i = j;
}

4.将native code编译成shared library供Java调用,针对Linux来说 就是.so文件,针对Windows来说就是.dll文

件,Linux下用g++、gcc进行编译,这里不对其进行介绍,毕竟不难。对Windows来说,编译生成dll一般是通过vc

来完成的。Windows下的动态链接库分为win32 dll和mfc dll,其中win32 dll可以供各种语言调用,而mfc dll则

会受到一些限制。这里介绍win32 dll。
生成一个win32 dll,要定义被导出的函数,有两种方式,函数名称前加_declspec(dllexport)或者定义def

文件,然后用vc进行编译,这样做并不算复杂,但是我发现了一种更容易的方法,我们只需要按照c/c++的语法规

范实现native函数,不需要定义被导出的函数,然后调用vc的编译工具cl.exe就可以了。
首先将testdll.h和my.c拷贝到Microsoft Visual Studio x.x\VC\bin中,同时将jdk中include目录中的所有文件

也都拷贝到Microsoft Visual Studio x.x\VC\bin中(这样做不是必须的,但是如果不这样,你调用cl命令的时

候就要带上一大串路径信息),接着调出vs再带的命令行工具,进入bin目录,然后执行cl -I . -LD my.c -

Femy.dll(.表示当前目录,I表示将在当前目录搜索包含的头文件,-LD后面表示源文件,-Fe后面紧跟的是目标文

件),ok,my.dll生成了,将my.dll拷贝到Java文件所在的目录,执行Java命令,成功执行。

上面只是个简单的示例,实际开发中还会有一些需要注意的问题,比如各种类型参数的传递,native code调用

dll或so的情况,这里就不做介绍了,完毕。

转载于:https://my.oschina.net/u/2336511/blog/392389

相关文章:

  • linux ubuntu ElasticSearch 安装 基本使用
  • iTunesU无法上传,决定放弃
  • Netty线程模型详解
  • 联想昭阳e43l笔记本配置
  • jquery 绘图工具 flot 学习笔记
  • 正则表达式之egrep实战示例
  • Java多线程编程(5)-volatile和synchronized比较
  • 如何将数据库账号(用户)解锁
  • 初窥Linux 之 最常用20条命令
  • 从百小度看人工智能
  • nuget的使用总结
  • 解读敏捷 之 响应变化高于遵循计划
  • java框架篇---hibernate入门
  • @javax.ws.rs Webservice注解
  • webservice测试窗体只能用于来自本地计算机的请求
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • JavaScript中的对象个人分享
  • 高度不固定时垂直居中
  • 汉诺塔算法
  • 基于axios的vue插件,让http请求更简单
  • 聊聊sentinel的DegradeSlot
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 入门级的git使用指北
  • 回归生活:清理微信公众号
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​​​​​​​​​​​​​​Γ函数
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • $.ajax()方法详解
  • (NSDate) 时间 (time )比较
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)ssm码农论坛 毕业设计 231126
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (顺序)容器的好伴侣 --- 容器适配器
  • (一)插入排序
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)memcache、redis缓存
  • (转)创业的注意事项
  • *Django中的Ajax 纯js的书写样式1
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Core 成都线下面基会拉开序幕
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @Controller和@RestController的区别?
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [ai笔记3] ai春晚观后感-谈谈ai与艺术