JNA的使用

 一、了解JNA
JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个 java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。
二、JNA的优点
JNA可以让你像调用一般java方法一样直接调用本地方法。就和直接执行本地方法差不多,而且调用本地方法还不用额外的其他处理或者配置什么的,也不需要多余的引用或者编码,使用很方便。
三、JNA描述
JNA类库使用一个很小的本地类库sub 动态的调用 本地代码。程序员只需要使用一个特定的 java接口描述一下将要调用的本地代码的方法的结构和一些基本属性。这样就省了为了适配多个平台而大量的配置和编译代码。因为调用的都是JNA提供的公用jar 包中的接口。JNA其目标是为了程序员调用本地代码更方便,跑的更快以及减少出错。
四、使用情景
在linux服务器上进行安卓的构建apk的时候要调用shell脚本进行打包处理。在服务器内存小的情况下,和用户并发量大的时候使用exec()执行shell就变成了一个比较危险的事情,执行一个脚本没有结束另一个中执行的脚本就会复制使用的内存,这样就会加速内存的消耗,内存还没有来得及减小就已经导致无法提供下一个shell脚本需要的内存导致程序执行失败。想到了JNA,使用JNA的方式调用动态链接库,在一定程度上解决了这个问题,但是消耗内存的问题依旧,最终还是采用了换一个大内存的服务器解决此问题,但是使用JNA还是有很大的改善加上使用大内存的服务器就没有再次出现内存不够的情况。
ps:JNA是同步的。
如果有错误的地方还望大家指正。
五、使用及参考代码
需要引入JNA需要的Jar包:http://download.csdn.net/detail/limm33/9467659
JNA的官方文档及代码:https://github.com/java-native-access/jna
import com.sun.jna.Native;
import com.sun.jna.Platform;


public class JNAUtil {
private static final Log logger = LogFactory.getLog(JNAUtil.class);


private interface CLibrary extends Library {
CLibrary WINDOWINSTANCE = (CLibrary) Native.loadLibrary(
(Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);


int system(String cmd);
}


private static int execW(String command) {
return CLibrary.WINDOWINSTANCE.system(command);
}


public static void execCommand(String cmd) throws IOException {
execW(cmd);
}
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用 JNA 调用 Windows API 可以实现模拟键盘事件。以下是一个示例代码,使用 `SendInput` 函数发送键盘事件: ```java import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.User32; import com.sun.jna.platform.win32.WinDef; import com.sun.jna.platform.win32.WinUser; public class Main { public static void main(String[] args) { User32 user32 = User32.INSTANCE; // 模拟按下键盘按键 int VK_A = 0x41; // A键的虚拟键码 WinUser.INPUT input = new WinUser.INPUT(); input.type = new WinDef.DWORD(WinUser.INPUT.INPUT_KEYBOARD); input.input.setType("ki"); input.input.ki.wScan = 0; input.input.ki.time = 0; input.input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0); input.input.ki.wVk = new WinDef.WORD(VK_A); input.input.ki.dwFlags = new WinDef.DWORD(0); // 0 表示按下键盘按键 user32.SendInput(new WinDef.DWORD(1), (WinUser.INPUT[]) input.toArray(1), input.size()); // 模拟释放键盘按键 input.input.ki.dwFlags = new WinDef.DWORD(WinUser.KEYEVENTF_KEYUP); // KEYEVENTF_KEYUP 表示释放键盘按键 user32.SendInput(new WinDef.DWORD(1), (WinUser.INPUT[]) input.toArray(1), input.size()); } } ``` 在上面的示例代码中,我们使用 `User32.INSTANCE` 获取 JNA 接口,然后定义了一个 `WinUser.INPUT` 结构体来存储键盘事件的信息。`SendInput` 函数用于发送输入事件,第一个参数是发送事件的个数,第二个参数是一个 `WinUser.INPUT` 数组,第三个参数是数组元素的大小。在发送键盘事件时,我们需要设置对应的虚拟键码和键盘事件类型,具体可以参考 Windows API 文档。 另外需要注意的是,为了发送键盘事件,程序需要获取 `SE_DEBUG_NAME` 权限,否则会报错。可以在程序启动时使用 `Advapi32.INSTANCE.OpenProcessToken` 函数获取当前进程的访问令牌,然后使用 `Advapi32.INSTANCE.LookupPrivilegeValue` 函数获取 `SE_DEBUG_NAME` 权限的 LUID,最后使用 `Advapi32.INSTANCE.AdjustTokenPrivileges` 函数开启 `SE_DEBUG_NAME` 权限。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值