`
mazhongjia
  • 浏览: 25394 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
最近访客 更多访客>>
社区版块
存档分类
最新评论

JNIHelloWorld

阅读更多

文章内容如题,只是对JNI使用的简单介绍。相信有许多同行也跟我一样在这方面知之甚少,所有在这里也总结一下,希望方便大家学习。

 

1.简介

JNI是Java Native Interface的缩写,它的设计目的是:

The standard Java class library may not support the platform-dependent features needed by your application.

You may already have a library or application written in another programming language and you wish to make it accessible to Java applications.

You may want to implement a small portion of time-critical code in a lower-level programming language, such as assembly, and then have your Java application call these functions

2.JNI的书写步骤

 1)编写带有native声明方法的java类。

 2)使用javac命令编译所编写的java类。

 3)使用编译后的.class文件,运行javah -jni 类名 命令生成扩展名为.h的头文件。

 4)使用C/C++实现本地方法。

    也就是自定义native方法所调用的其他语言的文件,该文件中实现java中声明的native方法(本文以c语言为例,所以建立文件为.c扩展名)。

 5)使用C/C++编写的文件(上述过程生成的.c文件)生成动态链接库文件。

    即使用cl.exe命令

 

   以上诸步骤我的理解总结如下:在java文件中如果想调用c的方法,需要通过声明的native方法来调用,调用什么方法呢,按照面向接口编程的思想需要事先定义一个供二者通信的接口吧,于是乎.h文件就出现了,java端通过javah命令生成这个接口文件,文件中声明了那些native方法,但是仅仅是定义一些基本信息(毕竟是接口嘛)比如:方法名、返回值、参数等。接口有了,想使用的话就需要对他进行实现了,这时就需要使用native语言(本例为C)对接口中方法进行实现了,这时就出现了步骤4中的.c扩展名的文件。文件有了还不行,需要对其进行转换,生成一个.dll文件,才能被java所使用,到了这一步大功告成。

 

下面就通过一个简单的helloworld实例演示上面的步骤:

 1)编写java程序:

public class HelloWorld {
	//Load动态库:System.loadLibrary("hello");加载动态库(我们可以这样理解:我们的方法displayHelloWorld()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。
	static {
		System.loadLibrary("hello");
	}
	//声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。
	public native void displayHelloWorld();
	//测试
	public static void main(String[] args){
		new HelloWorld().displayHelloWorld();
	}
} 

2)编译成.class文件

javac HelloWorld.java

 3)生成扩展名为.h的头文件

javah -jni HelloWorld

生成的头文件的内容:

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

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    displayHelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

这里我们可以这样理解:这个h文件相当于我们在java里面的接口,这里声明了一个Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致。如果需要在包深层次的某个class文件进行.h头文件的生成。则需要进行如下步骤:
 ·通过命令行进入到工程bin文件夹中
 ·输入命令:javah -classpath . packagepath.类名
    以上命令将产生一个名为:packagepath_类名.h 的头文件(其中packagepath路径中.被替换成_出现在文件名中)

需要注意:方法名中一定要正确指向其实现的方法所在的.h文件,不然虽然能正确进行下面步骤,但是运行时却出现异常。例如:生成的.h文件名为:com_mazhj_HelloWorld.h,则.c文件中相应的实现方法名应该为:Java_com_mazhj_HelloWorld_displayHelloWorld(JNIEnv *, jobject)

 4)编写本地方法

实现和由javah命令生成的头文件里面声明的方法名相同的方法。

 #include "jni.h"
 #include "HelloWorld.h"
 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
 {
       printf("Hello world!\n");
   return;
 }

 注意代码中的第1行,需要将jni.h文件引入,(可以在%JAVA_HOME%/include文件夹中找到)因为在程序中的JNIEnv、jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入(以便将HelloWorld.h头文件里面声明的方法加以实现)。最后将上面代码保存为HelloWorldImpl.c文件。

 5)生成动态库文件

以window平台为例,需要生成dll文件。在保存的HelloWorldImpl.c文件夹下面,使用VC的编译器cl.exe工具生成。

cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD HelloWorldImp.c -Fehello.dll

下面对该命令进行一下简单的介绍:

·CL.exe 是控制 Microsoft C 和 C++ 编译器与链接器的 32 位工具。编译器产生通用对象文件格式 (COFF) 对象 (.obj) 文件。链接器产生可执行文件 (.exe) 或动态链接库文件 (DLL)。

·参数-I:在目录中搜索包含文件。

   参数-LD:创建动态链接库。

   参数-Fe:重命名可执行文件

注意:生成的dll文件名在选项-Fe后面进行配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32参数加上,是因为在第4步里面编写本地方法的时候引入了jni.h文件。
  

   6)运行程序

java HelloWorld

 

注意:生成的.dll文件需要放在系统path中,这样,Java进程在运行中才能找到本地库并动态加载。我们可以通过环境变量System.getProperty("java.library.path")来查看当前JVM搜索本地库的路径,这时,就会遇到一个问题,部署应用的时候要记住将本地库拷贝到环境变量path指定的路径中。一般在windows平台上直接copy到C:\WINDOWS\System32目录下了事(此方法好使)。但要换一台机器部署怎么办?除了要把Java程序拿过去,还要记的把本地库也copy到正确的目录,真麻烦。于是想看看有什么好办法来解决这个问题。首先,最容易想到的是,把本地库和class文件放在一起,利用Class.getResource(str)找到路径,然后加到环境java.library.path中:

URL url = Foo.class.getResource("Foo.class");   
String path = (new File(url.getPath())).getParent();   
System.setProperty("java.library.path", path);  

看上去很好,但却不能工作。查了一下ClassLoader的源代码,原来它把搜索路径定义为静态变量并只初始化一次,后面再设置java.library.path就没有用了。 ClassLoader代码片断:

// The paths searched for libraries   
static private String usr_paths[];   
static private String sys_paths[];   
...   
if (sys_paths == null) {   
    usr_paths = initializePath("java.library.path");   
    sys_paths = initializePath("sun.boot.library.path");   
}  

 正在一筹莫展是,翻看JACOB的源代码,忽然有了惊喜的发现。 

try  
{   
    //Finds a stream to the dll. Change path/class if necessary   
    InputStream inputStream = getClass().getResource("/jacob.dll").openStream();   
    //Change name if necessary   
    File temporaryDll = File.createTempFile("jacob", ".dll");   
    FileOutputStream outputStream = new FileOutputStream(temporaryDll);   
    byte[] array = new byte[8192];   
    for (int i = inputStream.read(array); i != -1; i = inputStream.read(array)) {   
                outputStream.write(array, 0, i);   
        }   
    outputStream.close();   
    temporaryDll.deleteOnExit();   
    System.load(temporaryDll.getPath());   
    return true;   
}   
catch(Throwable e)   
{   
    e.printStackTrace();   
    return false;   
}  

 高,真是好办法。把dll放在classpath中,用Class.getResource(str).openStream()读取这个dll,然后写到temp目录中,最后用System.load(path)来动态加载。多说一句,为什么得到了jacob.dll的URL不直接去加载呢?想想看,如果把dll和class一起打成Jar包,ClassLoader还是不能加载本地库,因为System.load(path)需要的是dll的完整路径,但并不支持jar协议。还不明白,看看下面的代码:

 

URL url = Foo.class.getResource("/java/lang/String.class");   
System.out.println(url.toExternalForm());   
System.out.println(url.getFile());  

 

运行结果:

jar:file:/C:/Program%20Files/Java/jdk1.6.0_21/jre/lib/rt.jar!/java/lang/String.class
file:/C:/Program%20Files/Java/jdk1.6.0_21/jre/lib/rt.jar!/java/lang/String.class

 ClassLoader中用new File(name),当然会找不到文件。同时,看看我的第一种方法,就算能设置成功环境java.library.path,如果dll是在jar包中,还是加载不了。

 

 

 

附:VC编译器下载地址:http://www.oamo.com/Software/Catalog130/1569.html

分享到:
评论

相关推荐

    Android_JNI_Helloworld:Android Studio的安装项目以使用NDK

    私有原生String jniHelloWorld(); 使用javah生成C ++头 cd projectPath / app / src / main javah -d jni -cp pathTo / Library / Android / sdk / platforms / android-22 / android.jar:../../ build / ...

    基于springboot开发的前后端分离的简易进销存后台管理系统.zip

    基于springboot的java毕业&课程设计

    基于springboot-mqtt的温度、湿度、六氟化硫浓度实时监控系统.zip

    基于springboot的java毕业&课程设计

    会计信息化对华强公司内部审计的影响研究.docx

    会计信息化对华强公司内部审计的影响研究.docx

    修改谷歌提供的样例量子卷积神经网络模型,基于KDD99数据集进行训练,实现了网络攻击分类检测。.zip

    卷积神经网络(Convolutional Neural Networks, CNNs 或 ConvNets)是一类深度神经网络,特别擅长处理图像相关的机器学习和深度学习任务。它们的名称来源于网络中使用了一种叫做卷积的数学运算。以下是卷积神经网络的一些关键组件和特性: 卷积层(Convolutional Layer): 卷积层是CNN的核心组件。它们通过一组可学习的滤波器(或称为卷积核、卷积器)在输入图像(或上一层的输出特征图)上滑动来工作。 滤波器和图像之间的卷积操作生成输出特征图,该特征图反映了滤波器所捕捉的局部图像特性(如边缘、角点等)。 通过使用多个滤波器,卷积层可以提取输入图像中的多种特征。 激活函数(Activation Function): 在卷积操作之后,通常会应用一个激活函数(如ReLU、Sigmoid或tanh)来增加网络的非线性。 池化层(Pooling Layer): 池化层通常位于卷积层之后,用于降低特征图的维度(空间尺寸),减少计算量和参数数量,同时保持特征的空间层次结构。 常见的池化操作包括最大池化(Max Pooling)和平均池化(Average Pooling)。 全连接层(Fully Connected Layer): 在CNN的末端,通常会有几层全连接层(也称为密集层或线性层)。这些层中的每个神经元都与前一层的所有神经元连接。 全连接层通常用于对提取的特征进行分类或回归。 训练过程: CNN的训练过程与其他深度学习模型类似,通过反向传播算法和梯度下降(或其变种)来优化网络参数(如滤波器权重和偏置)。 训练数据通常被分为多个批次(mini-batches),并在每个批次上迭代更新网络参数。 应用: CNN在计算机视觉领域有着广泛的应用,包括图像分类、目标检测、图像分割、人脸识别等。 它们也已被扩展到处理其他类型的数据,如文本(通过卷积一维序列)和音频(通过卷积时间序列)。 随着深度学习技术的发展,卷积神经网络的结构和设计也在不断演变,出现了许多新的变体和改进,如残差网络(ResNet)、深度卷积生成对抗网络(DCGAN)等。

    用泽尼克多项式拟合表面的功能matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    毕业设计基于java+Springboot+协同过滤的新闻推荐系统源码+全部资料(高分项目).zip

    毕业设计基于java+Springboot+协同过滤的新闻推荐系统源码+全部资料(高分项目本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。毕业设计基于java+Springboot+协同过滤的新闻推荐系统源码+全部资料(高分项目毕业设计基于java+Springboot+协同过滤的新闻推荐系统源码+全部资料(高分项目毕业设计基于java+Springboot+协同过滤的新闻推荐系统源码+全部资

    基于vue可视化前段开发的拖拽编辑,页面生成工具.zip

    基于vue可视化前段开发的拖拽编辑,页面生成工具.zip

    HLC直播视频流播放器

    HLC直播视频播放器示例代码,代码2021年的时候因工作需要实现,参考网上资源采用了jquery等框架。

    基于卷积循环神经网络的数字识别.zip

    基于卷积循环神经网络的数字识别

    课设毕设基于SpringBoot+Vue的家具销售电商平台 LW+PPT+源码可运行.zip

    课设毕设基于SpringBoot+Vue的家具销售电商平台 LW+PPT+源码可运行.zip

    2007开关稳压电源(E题).doc

    包含作品的设计论文doc文档,可直接修改,适合于电赛备赛、课程设计、毕设参考等。 摘 要 该电源以单端反激式DC-DC变换器为核心。市电通过自耦式调压器,隔离变压器,整流滤波后产生直流电压,经DC-DC变换得到题目所需输出电压,实现了开关稳压电源的设计。DC-DC变换器采用脉宽调制器(PWM)UC3842,通过调节占空因数使得输出电压UO在30V~36V范围内可调;微控制器与键盘显示构成了控制显示模块,能对输出电压进行键盘设定和步进调整,并显示输出电压、电流的测量和数字显示功能,形成了良好的人机界面。 关键词:DC-DC变换器,脉宽调制器(PWM)

    520节日画图代码.zip

    520是每年的5月20日,因数字“520”与“我爱你”发音相似而被许多年轻人用作表达爱意的节日。这个节日起源于中国互联网文化,逐渐传递到其他国家和地区。在这一天,情侣们通常会互送礼物、发表情、或者举行浪漫的活动来庆祝爱情。快来领取专属于程序员的浪漫吧!表白的套路很多,但都少不了送花送礼物,作为一个程序员,搞不懂现在流行的泡泡机、小猪、重力感应车等玩具,也不想去让朋友们去送钱炫耀,毕竟真情才重要,钱就物质了。我能给各位单身粉丝们做的可能就只有分享几个表白代码了,在电脑上敲上几行代码,让她在郁闷的周一得到一个大大的惊喜,很简单,一看就会,如果现在用不到也不要紧,先收藏起来,反正这样的节日很多,以后用的时候能找到。

    带你学AI基于PP-OCR和ErnieBot的字幕提取和智能视频问答

    本次分享将带领大家从 0 到 1 完成一个基于 OCR 和 LLM 的视频字幕提取和智能视频问答项目,通过 OCR 实现视频字幕提取,采用 ErnieBot 完成对视频字幕内容的理解,并回答相关问题,最后采用 Gradio 搭建应用。本项目旨在帮助初学者快速搭建入门级 AI 应用,并分享开发过程中遇到的一些坑,希望对感兴趣的同学提供一点帮助。 参考https://blog.csdn.net/u010522887/article/details/139025542,跟随笔者共同走完一个完整的视频问答项目,从基础的动手跑通 CRNN 文本识别任务,再到应用开发和部署,旨在帮助初学者快速入门 OCR 相关技术并搭建一个简单的应用。 资源包包括前端文档中提到的源码和示例视频。 本系列的后续文章将沿袭这一思路,继续分享更多采用 Paddle 深度学习框架服务更多产业应用的案例。如果对你有帮助,欢迎 **关注 收藏** 支持

    毕设设计-学生宿舍管理系统 基于SpringBoot实现,界面简洁,功能完善

    毕设设计-学生宿舍管理系统 基于SpringBoot实现,界面简洁,功能完善 主要功能 ● 定位打卡、宿舍智能分配、学生信息管理、资讯管理(权限设计)等 使用 ● mysql、git、springboot ● 数据库初始化sql存储在doc文件夹下面 设计一个基于Spring Boot的学生宿舍管理系统,你需要确保系统既满足实用性,又保证界面简洁、功能完善。以下是一个基本的设计方案,包括系统的功能模块、技术栈选择和界面设计要点。 ### 功能模块 1. **用户认证模块**: - 登录/登出功能。 - 用户权限管理(如学生、宿舍管理员、系统管理员)。 2. **学生信息管理**: - 学生基本信息录入、查询、修改和删除。 - 宿舍分配与调换。 3. **宿舍楼管理**: - 宿舍楼信息维护。 - 宿舍房间信息管理。 4. **维修报修管理**: - 学生报修申请。 - 维修状态跟踪。 5. **来访登记管理**: - 来访人员登记。 - 访问记录查询。 6. **公告与通知发布**: - 发布宿舍相关公告和通知。

    一个前后端分离的仿知乎问答论坛.zip

    基于springboot的java毕业&课程设计

    课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip

    课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip课程设计 基于Python的机器学习的人脸

    基于springboot+thymeleaf构建的保险出单系统(含后台管理系统).zip

    基于springboot的java毕业&课程设计

    基于matlab鲸鱼优化随机森林WOA-RF数据分类(含数据)

    【RF分类】基于matlab鲸鱼优化随机森林WOA-RF数据分类MATLAB程序

Global site tag (gtag.js) - Google Analytics