JAVA JNA

原创 2011年01月21日 11:47:00

JNA支持的JAVA和本地代码之间的映射关系

Native Type    Size    Java Language Type    Common Windows Types
char     8-bit integer     byte     BYTE, TCHAR
short     16-bit     short     short WORD
wchar_t     16/32-bit character     char     WCHAR, TCHAR
int     32-bit integer     int     DWORD
int     boolean value     boolean     BOOL
long     32/64-bit integer     NativeLong     LONG
long long, __int64     64-bit integer     long      
float     32-bit FP     float      
double     64-bit FP     double      
char*     C string     String     LPTCSTR
void*     pointer     Pointer     LPVOID, HANDLE, LPXXX


使用JNA替代JNI调用本地方法

JNA全称是Java Native Access,是Sun推出的一种调用本地方法技术,比起它的同门师兄JNI,JNA大大简化了调用本地方法的过程,使用也比较方便, JNA是在JNI的基础上完善的,用青出于蓝而胜于蓝来形容一点不为过,下面看一下JNI的调用过程:   

使用JNI你得完成上面这些步骤,比较麻烦,而是用JNA就省事多了,基本上不需要脱离Java环境就可以完成。

JNA项目主页是https://jna.dev.java.net/, 目前最新的版本是3.2.4 。下载时记得将自带的Example.jar 也下载下来,这个里面提供了一些JNA的例子,通过这个能够更快的了解JNA。

使用JNA的调用本地方法的时候需要自定义数据结构,下面我们通过调用Windows提供的的锁定工作站方法来了解一下JNA。

1、首先查询Windows API知道锁定工作站的方法在user32.dll中定义,接下来定义一个接口来继承JNA的Library.java接口,用作声明DLL库文件,这里我们就把它命名为User32:     
public interface User32 extends Library {}

2、查询user32.dll提供的API得知锁定工作方法是LockWorkStation,返回类型是boolean型,在User32.java中新增相应的方法:
boolean LockWorkStation();
这样我们的User32.java这个类就定义好了。接下来我们写测试程序进行调用。

3、编写测试类比如LockWorkStation.java,首先通过JNA的Native类加载对应的dll:    
User32 user32 = (User32) Native.loadLibrary("user32", User32.class);

然后就可以调用LockWorkStation方法了,完整代码如下:     
public class LockWorkStation {
public static void main(String[] args) {
    User32 user32 = (User32) Native.loadLibrary("user32", User32.class);
    user32.LockWorkStation();
}
}

这里说明一下loadLibrary方法中第一个参数是需要加载的dll文件名称,第二个参数的作用是让JNA使用这个类的加载器去加载DLL文件,加载顺序是,先从Users.class类的当前文件夹找,如果没有找到,再在工程当前文件夹下面找win32/win64文件夹,找到后搜索对应的dll文件,如果找不到再到WINDOWS下面去搜索,再找不到就会抛异常了。以TWAINDSM.dll将文件放到工程的根文件夹可以按照下面这个格式放:
上面的User32定义的是dll库文件,有时会碰到比如HANDLE、POINT、WORD和MSG等数据类型,有些数据类型JNA中没有提供,需要自己定义,根据作用的不同,定义的时候继承的父类也不一样,比如HANDLE定义方法是:
class HANDLE extends PointerType {
    private boolean immutable;
    public HANDLE() { }
    public HANDLE(Pointer p) { setPointer(p); immutable = true; }
    public Object fromNative(Object nativeValue, FromNativeContext context) {
      Object o = super.fromNative(nativeValue, context);
      if (INVALID_HANDLE_VALUE.equals(o))
            return INVALID_HANDLE_VALUE;
      return o;
  }
    public void setPointer(Pointer p) {
        if (immutable)
            throw new UnsupportedOperationException("immutable reference");
        super.setPointer(p);
    }
}
HANDLE被定义为类型安全的指针。而POINT用作表示坐标,不需要这么复杂,定义方式为:
class POINT extends Structure {
    public int x, y;
    public POINT() { }
    public POINT(int x, int y) { this.x = x; this.y = y; }
}

使用JNA的过程中也不一定会一帆风顺,比如会抛出”非法内存访问”,这时候检查一下变量是否==null。还有内存对齐的问题,当从内存中获取图片信息进行保存的时候,如果内存对齐处理不好,就会抛出很严重的异常,导致JVM异常退出,JNA提供了四种内存对齐的方式,分别是:ALIGN_DEFAULT、ALIGN_NONE、ALIGN_GNUC和ALIGN_MSVC。ALIGN_DEFAULT采用平台默认的对齐方式(推荐);ALIGN_NONE是不采用对齐方式;ALIGN_GNUC为针对linux/gcc操作系统的对齐方式。ALIGN_MSVC为针对win32/msvc架构的内存对齐方式。

JNA也提供了一种保护机制.比如防止JNA出现异常不会导致JVM异常退出,默认是开启这个功能的,开启方式为 System.setProperty(“jna.protected”,”true”); 记得要在JNA加载dll文件之前调用,然后try {...} catch(Throwable e)异常,不过你也不要期望过高,不要以为加上这个就万事大吉,出现”非法内存访问”的时候还是会束手无策。JNA也提供了一种保护机制.比如防止JNA 出现异常不会导致JVM异常退出,默认是开启这个功能的,开启方式为 System.setProperty(“jna.protected”,”true”); 记得要在JNA加载dll文件之前调用,然后try {...} catch(Throwable e)异常,不过你也不要期望过高,不要以为加上这个就万事大吉,出现”非法内存访问”的时候还是会束手无策。

痛苦Java的JNA使用-byte流转换使用

最近因为一个项目,改造客户现有系统,
  • wangfengwf
  • wangfengwf
  • 2014年11月19日 16:16
  • 3281

Java 调用 C/C++ 之 JNA 系列实战篇 —— 输入wchar_t* (二)

一、 工作环境
  • abelabel
  • abelabel
  • 2014年06月06日 13:44
  • 1421

java本地调用 - JNA技术

#JAVA 本地调用 - JNA技术 ##JNI回顾 JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interfa...
  • conquer0715
  • conquer0715
  • 2014年06月23日 12:56
  • 6046

java通过 JNA调用 so

 JNA—JNI终结者   介绍 给大家介绍一个最新的访问本机代码的Java框架—JNA。 JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开...
  • a936676463
  • a936676463
  • 2015年11月28日 10:56
  • 7023

LINUX 下 JNA 调用 so--正确版

项目中需要用到JAVA调用c++,了解过JNI,但比较复杂,后来看到JNA(JNI的加强版)。 网上看了很多例子,但是始终出错,主要错误原因是undefined symbol,找不到c++ 方法。 ...
  • u013242491
  • u013242491
  • 2014年03月16日 10:14
  • 2659

Java调用C语言动态库(JNA方式):回调函数、结构体数组传参、结构体数组返回

一、开发环境 系统、开发环境:win7、eclipse 32位、jdk 32位、jre 32位 由于这里使用的dll文件是32位的,而我本身的环境是64位的,包括eclipse、jdk、jre都是...
  • ggmove
  • ggmove
  • 2013年12月17日 16:13
  • 6692

JNA java调用c/c++代码

最近在搞一个小程序,需要用java调用DLL。用到的技术是JNA。 具体的内容在网上一搜都有,但是很多帖子内容都差不多,而且都有些问题,也不知道是不是版本的问题,反正代码拿来一copy各种问题,倒腾...
  • xueerfei008
  • xueerfei008
  • 2013年08月11日 12:45
  • 9963

JNA方式调用dll动态库

java调用dll较为常用的方式有JNA和JNI,JNA方式较为简便。 附代码:
  • qq_22681061
  • qq_22681061
  • 2016年12月25日 18:15
  • 1186

jna对结构体、指针、引用、拷贝参数传递的使用

虽然之前也用过jna,但是对于结构体的传递、指针参数数与返回值、引用参数与返回值、拷贝变量传递使用没有总结。 先上生成DLL代码: //dllTest.h#ifndef DLLTEST_H #defi...
  • baby6046
  • baby6046
  • 2015年11月13日 10:42
  • 5878

使用JNA,让java调用原生代码

JNA定义:JNA:java Native Access,是SUN公司开发的基于JNI的框架,JNI使得Java能够调用原生的c或者c++代码。JNA与JNI的区别:性能:JNA在性能上不如JNI,由...
  • lanran2
  • lanran2
  • 2016年01月16日 19:48
  • 5458
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JAVA JNA
举报原因:
原因补充:

(最多只允许输入30个字)