`

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

    博客分类:
  • java
阅读更多

 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中定义,接下来定义一个接口来继承JNALibrary.java接口,用作声明DLL库文件,这里我们就把它命名为User32:      

 public interface User32 extends Library {}

    2查询user32.dll提供的API得知锁定工作方法是LockWorkStation,返回类型是boolean型,在User32.java中新增相应的方法:

boolean LockWorkStation();

         这样我们的User32.java这个类就定义好了。接下来我们写测试程序进行调用。

    3、编写测试类比如LockWorkStation.java,首先通过JNANative类加载对应的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下面去搜索,再找不到就会抛异常了。

   上面的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_DEFAULTALIGN_NONEALIGN_GNUCALIGN_MSVCALIGN_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 楼 jim19770812 2011-03-19  
根据你的文章,解决了我的程序崩溃的问题,多谢

相关推荐

    使用JNA替代JNI调用DLL,并解决内存溢出问题

    ### 使用JNA替代JNI调用DLL,并解决内存溢出问题 #### 问题背景 在项目的开发过程中,常常遇到需要处理二进制流数据并对其进行解析处理的情况。这种情况下,如果上层应用平台采用的是Java开发,而底层算法或数据...

    springboot+jna/jni调用动态so/dll库

    在这种情况下,"springboot+jna/jni调用动态so/dll库"是一个重要的主题,它涉及到Spring Boot应用如何利用Java Native Interface (JNI) 和 Java Native Access (JNA) 这两种技术来调用操作系统级别的动态链接库(.so...

    JNA—JNI终结者(转载)

    这篇文章探讨的主题是Java Native Access (JNA) 和 Java Native Interface (JNI),两者都是Java平台上的技术,用于在Java应用程序中调用本地(非Java)代码。它们允许Java程序员与操作系统底层功能进行交互,如访问...

    jni调用C++动态库,jna调用C++动态库

    JNA是一种更高级、更易使用的替代方案,它通过映射Java方法到本地函数来避免JNI的复杂性。关键知识点包括: 1. **Interface定义**:在JNA中,我们定义一个接口,其中的方法对应于本地库的函数,JNA会自动处理参数和...

    jna-call-dll-and-C-call-java.zip_java dll_java dll 回调_jna_jna调用d

    JNI虽然强大,但编写和调试起来较为繁琐,而JNA则提供了一种相对简单、方便的替代方案。标题和描述中提到的是使用JNA来调用DLL(动态链接库)并在C中实现对Java的回调功能。 首先,让我们详细了解一下JNA的工作原理...

    jna参考手册(英文)

    JNA的出现是为了简化与本地代码交互的过程,它的目标是成为JNI的替代方案,因为JNI的使用通常涉及到大量的模板代码和编译步骤。 **JNA的核心概念:** 1. **Platform:** JNA的核心是一个`Platform`类,它包含了...

    JNA框架帮助文档

    为了简化这一过程并提高安全性,本文将介绍一个名为Java Native Access (JNA) 的开源项目,它可以替代传统JNI调用的方式,使得开发者可以直接在Java程序中调用C语言库。 #### 二、JNA框架概述 **1. 什么是JNA** ...

    jni如何使用

    此外,随着Java的发展,JNA(Java Native Access)和JNR(Java Native Runtime)等替代方案也逐渐流行,它们提供了更高级别的抽象,简化了与本地代码的交互。然而,对于特定的需求,如深度优化或访问低级系统功能,...

    java调用windows api

    2. **Java Native Access (JNA)**: JNA是一种更高级的接口,它消除了对JNI的直接使用,允许Java代码直接映射到本地函数。JNA提供了更简单的API,无需编写C/C++代码,而是通过Java接口来声明本地函数。 - **JNA配置...

    java jni技术分析

    此外,Java Native Access (JNA) 是一个替代方案,它提供了一种更高级别的接口,允许Java代码直接调用本地库,而无需编写C/C++代码。JNA使用Java接口映射到本地函数,简化了与本地代码交互的过程。 总的来说,JNI和...

    java调用vc的dll

    使用JNI调用DLL虽然能实现跨语言交互,但会带来一定的性能开销,因为Java与C/C++之间的数据转换和函数调用都需要额外的时间。如果频繁调用,可能影响程序性能。 8. **替代方案** 除了JNI,还可以考虑其他技术,如...

    java的JNI小联系

    - 对于大型项目,考虑使用JNI的现代替代品,如JNA(Java Native Access)或SWIG(Simplified Wrapper and Interface Generator)。 通过这个小练习,你可以亲手实现一个简单的JNI项目,比如从Java调用C++函数进行...

    Java调用本地库 JNAerator

    需要注意的是,虽然JNAerator大大简化了Java调用本地库的过程,但它并不能完全替代JNI。在处理性能敏感或需要高效内存管理的场景时,JNI可能仍然是更好的选择,因为它允许直接访问机器码,没有JNA的额外开销。但对...

    java_so

    1. 性能需求:当Java的性能无法满足某些计算密集型或I/O密集型任务时,可以使用JNI调用本地代码。 2. 兼容性:某些操作或功能只能通过本地库实现,例如与硬件设备的直接交互。 3. 利用现有库:如果已经有用C、C++...

    c++与Java互操作1

    - JNA是一个替代JNI的库,它的出现简化了与C/C++代码的交互。相比JNI,JNA提供了更简单的接口,不需要手动编写大量的JNI头文件和本地代码,而是直接映射Java方法到原生函数。 3. **在Java中使用JNI的步骤**: - *...

    JNA-Call-DLL.tar.gz

    Java调用DLL/so源代码JNA和JNative 调用现有的.dll/.so文件,使用JNI技术调用,我们首先需要另外使用C语言写一个.dll/.so共享库,使用SUN规定的数据结构替代C语言的数据结构,调用已有的dll/so中公布的函数。

    JNIO and Security

    标题中的“JNIO and Security”指的可能是Java Native Interface (JNI) 与安全性的结合,这涉及到Java程序如何通过JNI调用本地(Native)代码,并在此过程中如何确保系统的安全性。JNI是Java平台的一部分,允许Java...

    Windows文件路径选择的dll封装

    JNA(Java Native Access)则是另一种与JNI类似的机制,但它的使用更简洁,无需编写复杂的头文件和本地方法映射。JNA允许Java程序直接调用本地库函数,减少了开发过程中的工作量。通过JNA,我们可以轻松地访问...

    jacob-1.14.3.rar

    - Jacob与JNA(Java Native Access)的对比:JNA是另一种调用本地方法的框架,与Jacob相比,JNA更轻量级,但对COM组件的支持不如Jacob全面。 7. **未来发展趋势** - 虽然Jacob是一个成熟且稳定的库,但由于其依赖...

    常用Jacob包

    7. **性能考虑**:虽然Jacob提供了一种强大的功能,但由于涉及到JNI调用,其性能通常会比纯Java代码低。在性能敏感的场景下,需要权衡使用Jacob的利弊。 8. **版本兼容性**:Jacob的每个版本可能支持不同的Java和...

Global site tag (gtag.js) - Google Analytics