JNA 调用操作系统函数 和 系统调用
linux系统调用syscall 表:https://filippo.io/linux-syscall-table/
原文:https://iliangqunru.bitcron.com/post/2018/jna-shi-ji-kai-fa-zhong-ruo-gan-wen-ti-jie-jue-fang-fa
其他:
java发起系统调用,本质还是用了JNA,调用OS提供的syacall函数:
import com.sun.jna.Library;
import com.sun.jna.Native; public class Test {
public interface CStdLib extends Library {
int syscall(int number, Object... args);
} public static void main(String[] args) {
CStdLib c = (CStdLib)Native.loadLibrary("c", CStdLib.class); // WARNING: These syscall numbers are for x86 only
System.out.println("PID: " + c.syscall(20));
System.out.println("UID: " + c.syscall(24));
System.out.println("GID: " + c.syscall(47));
c.syscall(39, "/tmp/create-new-directory-here");
}
}
很早就已经听说过 JNI(Java Native Interface)Java 本地接口,奈何调用本地动态链接库太过于复杂,就一直没有再尝试。而最近因为工作需要调用 Windows DLL 动态链接库(对应 Linux 中 so 文件),而对 JNA 有了入坑体验,对实际工作中遇到的问题做出总结。
1. 调用 Windows 窗口打印Hello World
- pom 依赖
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>latest</version>
</dependency>
- JNA 在加载驱动时提供两种加载方式 , 直接映射 和 接口生成。
接口生成
public interface HelixcsDll extends StdCallLibrary {
// loadLibary 为动态链接库加载目录
HelixcsDll HELIXCS_DLL = Native.loadLibrary("helixcs.dll", HelixcsDll.class);
// 在 dll 中存在相同 SomeFunction 的函数
void SomeFunction(String content);
}
// 调用
HelixcsDll.HELIXCS_DLL.SomeFunction("Hello World");
直接映射
class Helixcs{
static {
Native.register("helixcs.dll");
}
// 映射为本地方法
public static native void SomeFunction(String content);
public static void main(String[] args) {
SomeFunction("Hello World");
}
}
官方例子:
package com.sun.jna.examples; import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform; /** Simple example of JNA interface mapping and usage. */
public class HelloWorld { // This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types. public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.load((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class); void printf(String format, Object... args);
} public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i=0;i < args.length;i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
2. C 类型和 Java 类型映射。
- JNA 官方提供的默认类型映射
Default Type Mappings 默认类型映射
Java primitive types (and their object equivalents) map directly to the native C type of the same size.
Java 原始类型以相同的大小映射 C 类型。
| Native Type | Size | Java Type | Common Windows Types |
| char | 8-bit integer | byte | BYTE, TCHAR |
| short | 16-bit integer | short | WORD |
| wchar_t | 16/32-bit character | char | TCHAR |
| int | 32-bit integer | int | DWORD |
| int | boolean value | boolean | BOOL |
| long | 32/64-bit integer | NativeLong | LONG |
| long long | 64-bit integer | long | __int64 |
| float | 32-bit FP | float | |
| double | 64-bit FP | double | |
| char* | C string | String | LPTCSTR |
| void* | pointer | Pointer | LPVOID, HANDLE, LPXXX |
未签名类型作为签名类型来映射。 C 中枚举类型可替换为 “int”。
Unsigned types use the same mappings as signed types. C enums are usually interchangeable with "int".
3. 官方提供的详细的类型映射
Marshalling/Unmarshalling (Java/Native Type Conversions)
| C Type | Native Representation | Java Type |
| char | 8-bit integer | byte |
| wchar_t | platform-dependent | char |
| short | 16-bit integer | short |
| int | 32-bit integer | int |
| int | boolean flag | boolean |
| enum | enumeration type | int (usually) |
| long long, __int64 | 64-bit integer | long |
| float | 32-bit floating point | float |
| double | 64-bit floating point | double |
| pointer (e.g. void*) | platform-dependent (32- or 64-bit pointer to memory) | BufferPointer |
| pointer (e.g. void*),array | 32- or 64-bit pointer to memory (argument/return)contiguous memory (struct member) | <P> |
In addition to the above types, which are supported at the native layer, the JNA Java library automatically handles the following types. All but NativeMapped and NativeLong are converted to Pointer before being passed to the native layer. |
||
| long | platform-dependent (32- or 64-bit integer) | NativeLong |
| const char* | NUL-terminated array (native encoding or jna.encoding) |
String |
| const wchar_t* | NUL-terminated array (unicode) | WString |
| char | NULL-terminated array of C strings | String[] |
| wchar_t | NULL-terminated array of wide C strings | WString[] |
| void** | NULL-terminated array of pointers | Pointer[] |
| struct*struct | pointer to struct (argument or return) (or explicitly)struct by value (member of struct) (or explicitly) |
Structure |
| union | same as Structure |
Union |
| struct[] | array of structs, contiguous in memory | Structure[] |
| void (*FP)() | function pointer (Java or native) | Callback |
| pointer (<T> *) | same as Pointer |
PointerType |
| other | integer type | IntegerType |
| other | custom mapping, depends on definition | NativeMapped |
4. 经验总结默认映射关系
尽管 JNA 官方已经提供了详细的类型映射文档。但在实际中发现按照官方映射可能出现莫名问题。对此我们在实际开发中对于一些类型的映射报错,可以参考以下映射做出调整。
| C类型 | JNA类型 | 说明 |
|---|---|---|
| char * out | Pointer | Pointer room = new Memory(30); |
| uchar * out | Pointer | Pointer room = new Memory(30); |
| long * | long [ ] | |
| int * | init [ ] | |
| int | int | |
| char * | byte [ ] | |
| char * argv[] | String [] | |
| uchar | int | |
| long | NativeLong | 兼容 32和64位 |
5. 常见错误
1. UnsatisfiedLinkError 问题
存在多个动态链接库之间调用情况,可能缺少其中某一个动态链接库文件。
2. Error Memory Access 问题
较大情况下存在参数类型映射错误,参考 JNA 类型映射。
3. dll can not find in win32/86
无法加载到动态链接库文件路径,需要将动态链接库放到项目根目录下,推荐开启 JNA 驱动加载 debug 模式,
System.setProperty("jna.debug_load", "true");
手动指定动态链接库文件路径
System.setProperty("jna.library.path",dllResourcePath);
System.setProperty("jna.platform.library.path",dllResourcePath);
4. 程序在运行一段时间后崩溃
在JNA crash-protection 中,官方文档说明的崩溃的主要原因,( These are often caused by improper mappings or invalid arguments passed to the native library.) 未知的参数类型映射导致vm崩溃。在很大程度上使用 Pointer 来作为 Java 通用映射类型。而 JNA 默认程序保护Native.setProtected(true)使得 java 错误来代替程序崩溃,可以设置 Native.setProtected(false) 来 dump 出崩溃日志。
问题可以反馈到 JNA Google Group : https://groups.google.com/forum/#!forum/jna-users
6. 参考
JNA Google Group : https://groups.google.com/forum/#!forum/jna-users
JNA API Documentation: https://java-native-access.github.io/jna/4.2.1/overview-summary.html
JNA VM Crashed Protection :http://java-native-access.github.io/jna/4.5.1/javadoc/overview-summary.html#crash-protection
JNA 调用操作系统函数 和 系统调用的更多相关文章
- Atitit.java jna 调用c c++ dll的原理与实践 总结 v2 q27
Atitit.java jna 调用c c++ dll的原理与实践 总结 v2 q27 1. Jna简单介绍1 2. Jna范例halo owrld1 3. Jna概念2 3.1. (1)需 ...
- Atitit.java jna 调用c++ dll 的总结
Atitit.java jna 调用c++ dll 的总结 1. JNA技术解密1 1.1. JNA工作原理1 2. JNA技术难点 Java—C和操作系统数据类型的对应表1 2.1. 1 2.2. ...
- Linux系统编程(1)——文件与I/O之C标准I/O函数与系统调用I/O
Linux系统的I/O也就是一般所说的低级I/O--操作系统提供的基本IO服务,与os绑定,特定于Linux平台.而标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头 ...
- RTX——第19章 SVC 中断方式调用用户函数(后期补历程)
以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解如何采用 SVC 中断方式调用用户函数. 当用户将 RTX 任务设置为工作在非特权级模式 ...
- JNA调用库文件
最近项目中要集成厂商的卡口摄像头,需要通过jna调用库函数接收卡口相机抓拍的过车数据.本文记录了Java调用C语言动态库(jna)的调用方式.回调函数.结构体等. JNA全称Java Native A ...
- Lua中调用C函数
Lua利用一个虚拟的堆栈来给C传递值或从C获取值.每当Lua调用C函数,都会获得一个新的堆栈,该堆栈初始包含所有的调用C函数所需要的参数值(Lua传给C函数的调用实参),并且C函数执行完毕后,会把返回 ...
- Linux 编程中的API函数和系统调用的关系【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...
- modelsim+win环境下systemverilog调用c函数
最近为了验证一个ip,需要将ip的输出数据与c model的数据比对,之前采用的是将仿真结果输出,用perl读取结果,与c的输出结果比对,这样做也可以,但是在做遍历测试时,由于数据量较大,就显得不方便 ...
- Lua中调用C函数(lua-5.2.3)
Lua能够调用C函数的能力将极大的提高Lua的可扩展性和可用性. 对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们全然能够通过C函数来实现,之后再通过Lua调用指定的C函数. 对于那些可 ...
随机推荐
- 硬件笔记之制作MacOS Mojave U盘USB启动安装盘方法
0x00 概述 随着苹果 macOS Mojave 正式版发布,很多使用 Mac 电脑的同学都已升级到最新版了.但如果你对系统有洁癖或原本系统已凌乱不堪,那么可能还是希望能格式化「全新安装 macOS ...
- IC卡、ID卡、M1卡、射频卡的区别是什么(射频卡是种通信技术)
IC卡.ID卡.M1卡.射频卡都是我们常见的一种智能卡,但是很多的顾客还是不清楚IC卡.ID卡.M1卡.射频卡的区别是什么,下面我们一起来看看吧. 所谓的IC卡就是集成电路卡,是继磁卡之后出现的又一种 ...
- 记录一次OracleJDK开发的项目发部到Linux中使用OpenJDK启动后失败的错误的解决方案
一.现象 基于JAVA SpringBoot2.0.4的项目,发部后项目发部后,放到OpenJDK环境中运行时,提示下列错误: 2019-10-22 10:03:55 [main] WARN o.s ...
- Java进程间通信学习
转自:https://www.iteye.com/blog/polim-1278435 进程间通信的主要方法有:(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共 ...
- 集合(set)
'''set是一个无序(不支持索引和切片)而且不重复的集合,有些类似于数学中的集合,也可以求交集,求并集等,''' s1={1,2,3,1} #定义一个set s1 如果s1={}为空则默认定义一个字 ...
- MySQL5.7 安装和配置环境变量
安装 1.下载安装包 官网地址:https://dev.mysql.com/downloads/mysql/ 2.选择 Custom,自定义 3.根据自己系统选择 x64还是x86,然后点击第一个箭头 ...
- Windows 系统常用命令
/** 环境变量配置 * sysdm.cpl */ /** 系统服务管理 * sservices.msc */ /** 远程服务器连接 * mstsc */ /** doc命令窗口 * doc */
- spark 修改默认log4j.properties 配置
spark-submit \ --files ${CONF_DIR}/log4j-driver.properties,${CONF_DIR}/log4j-executor.properties \ - ...
- 利用python制作在线视频播放器遇到的一些问题
经过前期的调研,我准备使用PyQT+PyAV+PyAudio+pillow.期间也尝试过使用ffmpeg-python,但最后还是选择了av这个更底层,自由度更大的库来完成音视频的处理. ==== ...
- sftp常用命令
help 查看sftp支持哪些命令 ls 查看当前目录下文件 cd 指定目录 lcd 更改和/或打印本地工作目录 pwd 查看当前目录 lpwd 打印本地工作目录 get xxx.txt 下载xxx ...