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)异常,不过你也不要期望过高,不要以为加上这个就万事大吉,出现”非法内存访问”的时候还是会束手无策。

最新文章

  1. Django基础,Day5 - form表单投票详解
  2. Solve
  3. UGUI
  4. 向Web开发人员推荐12款优秀的 Twitter Bootstrap 组件和工具
  5. java基础:熟悉3种内部类的写法,重点匿名内部类的使用
  6. 基础框架Fundation和UIkit框架的定义和使用
  7. poj1068解题报告(模拟类)
  8. shell 中函数放回字符串问题
  9. MFC调用c#的dll
  10. SVG矢量图学习实例
  11. Unity 角色移动贴墙行走
  12. Java多线程学习(四)---控制线程
  13. Servlet -- 中文乱码解决
  14. Mudo C++网络库第三章学习笔记
  15. C#生成ZIP压缩包
  16. 使用scrapy爬取海外网学习频道
  17. 个人博客-week7
  18. react学习笔记(二)编写第一个react组件
  19. js学习之--Bootstrap Modals(模态框)
  20. 使用JdbcTemplate访问数据库

热门文章

  1. ES-Result window is too large
  2. 【PAT甲级】1089 Insert or Merge (25 分)(插入排序和归并排序)
  3. 每个JavaScript开发人员应该知道的33个概念
  4. 【JQuery 选择器】 案例
  5. Git三招
  6. GCC 升级
  7. 07 DTFT
  8. UIKeyWindow的设置
  9. flask view
  10. 笔记-capped collection