使用JNI技术实现java程序调用第三方dll文件的功能

本文详细介绍了如何使用Java Native Interface (JNI) 技术在Java程序中调用第三方DLL文件,以实现与硬件设备的通信。通过创建Java类,声明native方法,并编写C/C++ DLL来桥接Java与设备商提供的DLL接口,从而解决Java无法直接与某些硬件通信的问题。文章还强调了使用JNI可能带来的跨平台性损失,并列举了适合使用JNI的场景。
摘要由CSDN通过智能技术生成

java:

JAVA的跨平台的特性深受java程序员们的喜爱,但正是由于它为了实现跨平台的目的,使得它和本地机器的各种内部联系变得很少,大大约束了它的功能,比如与一些硬件设备通信,往往要花费很大的精力去设计流程编写代码去管理设备端口,而且有一些设备厂商提供的硬件接口已经经过一定的封装和处理,不能直接使用java程序通过端口和设备通信,这种情况下就得考虑使用java程序去调用比较擅长同系统打交道的第三方程序,从1.1版本开始的JDK提供了解决这个问题的技术标准:JNI技术.
       JNI是Java Native Interface(Java本地接口)的缩写,本地是相对于java程序来说的,指直接运行在操作系统之上,与操作系统直接交互的程序.从1.1版本的JDK开始,JNI就作为标准平台的一部分发行.在JNI出现的初期是为了Java程序与本地已编译语言,尤其是C和C++的互操作而设计的,后来经过扩展也可以与c和c++之外的语言编写的程序交互,例如Delphi程序.
       使用JNI技术固然增强了java程序的性能和功能,但是它也破坏了java的跨平台的优点,影响程序的可移植性和安全性,例如由于其他语言(如C/C++)可能能够随意地分配对象/占用内存,Java的指针安全性得不到保证.但在有些情况下,使用JNI是可以接受的,甚至是必须的,例如上面提到的使用java程序调用硬件厂商提供的类库同设备通信等,目前市场上的许多读卡器设备就是这种情况.在这必须使用JNI的情况下,尽量把所有本地方法都封装在单个类中,这个类调用单个的本地库文件,并保证对于每种目标操作系统,都可以用特定于适当平台的版本替换这个文件,这样使用JNI得到的要比失去的多很多.
       现在开始讨论上面提到的问题,一般设备商会提供两种类型的类库文件,windows系统的会包含.dll/.h/.lib文件,而linux系统的会包含.so/.a文件,这里只讨论windows系统下的c/c++编译的dll文件调用方法.
       我把设备商提供的dll文件称之为第三方dll文件,之所以说第三方,是因为JNI直接调用的是按它的标准使用c/c++语言编译的dll文件,这个文件是客户程序员按照设备商提供的.h文件中的列出的方法编写的dll文件,我称之为第二方dll文件,真正调用设备商提供的dll文件的其实就是这个第二方dll文件.到这里,解决问题的思路已经产生了,大慨分可以分为三步:
       1>编写一个java类,这个类包含的方法是按照设备商提供的.h文件经过变形/转换处理过的,并且必须使用native定义.这个地方需要注意的问题是java程序中定义的方法不必追求和厂商提供的头文件列出的方法清单中的方法具有相同的名字/返回值/参数,因为一些参数类型如指针等在java中没法模拟,只要能保证这个方法能实现原dll文件中的方法提供的功能就行了;
       2>按JNI的规则使用c/c++语言编写一个dll程序;
       3>按dll调用dll的规则在自己编写的dll程序里面调用厂商提供的dll程序中定义的方法.

       我之前为了给一个java项目添加IC卡读写功能,曾经查了很多资料发现查到的资料都是只说到第二步,所以剩下的就只好自己动手研究了.下面结合具体的代码来按这三个步骤分析.

     1>假设厂商提供的.h文件中定义了一个我们需要的方法:
      __int16 __stdcall readData( HANDLE icdev, __int16 offset, __int16 len, unsigned char *data_buffer );
      a.__int16定义了一个不依赖于具体的硬件和软件环境,在任何环境下都占16 bit的整型数据(java中的int类型是32 bit),这个数据类型是vc++中特定的数据类型,所以我自己做的dll也是用的vc++来编译.
     b.__stdcall表示这个函数可以被其它程序调用,vc++编译的DLL欲被其他语言编写的程序调用,应将函数的调用方式声明为__stdcall方式,WINAPI都采用这种方式.c/c++语言默认的调用方式是__cdecl,所以在自己做可被java程序调用的dll时一定要加上__stdcall的声明,否则在java程序执行时会报类型不匹配的错误.
     c.HANDLE icdev是windows操作系统中的一个概念,属于win32的一种数据类型,代表一个核心对象在某一个进程中的唯一索引,不是指针,在知道这个索引代表的对象类型时可以强制转换成此类型的数据.
    这些知识都属于win32编程的范围,更为详细的win32资料可以查阅相关的文档.
    这个方法的原始含义是通过设备初始时产生的设备标志号icdev,读取从某字符串在内存空间中的相对超始位置offset开始的共len个字符,并存放到data_buffer指向的无符号字符类型的内存空间中,并返回一个16 bit的整型值来标志这次的读设备是否成功,这里真正需要的是unsigned char *这个指针指向的地址存放的数据,而j

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值