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函数. 对于那些可 ...
随机推荐
- MySQL、HBase、ES的对比
hbase是列数据库,是kv结构的,ES的基于Lucene的搜索引擎的面向文档数据库吧 ES是搜索引擎,主要的优势在于快速搜索,HBase是数据库,优势在于存储数据,侧重点不同 MySQL:关系型数据 ...
- C#实现outlook自动签名
Outlook下实现自动签名的方式 网上找到一篇资料是在outlook里用vba实现的,但是这样实现的方式由于数字认证的问题不便于部署 在此介绍一种C#下实现的方式,目前确定的outlook版本为 ...
- 关于VS C++中项目属性的一些名称的含义
这个属性页(Alt + F7)界面下的$开头的内容的含义 $(Platform), X64或X86类似的. $(SolutionDir),.sln的位置 $(Configuration), Debug ...
- File "tesserocr.pyx", line 2443, in tesserocr._tesserocr.image_to_text RuntimeError: Failed to in...
将Tesseract-OCR安装目录下的tessdata文件夹复制到Python解释器目录下就可以了
- 01GitLab的使用——创建项目并上传到GitLab
借鉴:https://jingyan.baidu.com/article/9c69d48fe68cce13c9024e9c.html 登录GitLab网站,创建一个项目上传地址:https://blo ...
- [转]【response】HttpServletResponse接口
创建时间:6.19 & 6.24 1.HttpServletResponse概述 我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参 ...
- 年薪30W测试工程师成长之路,你在哪个阶段?
对任何职业而言,薪资始终都会是众多追求的重要部分.前几年的软件测试行业还是一个风口,随着不断地转行人员以及毕业的大学生疯狂地涌入软件测试行业,目前软件测试行业“缺口”已经基本饱和.当然,我说的是最基础 ...
- Detectron2源码阅读笔记-(三)Dataset pipeline
构建data_loader原理步骤 # engine/default.py from detectron2.data import ( MetadataCatalog, build_detection ...
- django 权限设置 左侧菜单点击显示,面包屑
1.左侧菜单点击显示 就是在点击的时候保留点击的功能 方法. 1.加入新的字段,pid来判断 class Permission(models.Model): """ 权限 ...
- Java多线程编程核心技术-第7章-拾遗增补-读书笔记
第 7 章 拾遗增补 本章主要内容 线程组的使用. 如何切换线程状态. SimpleDataFormat 类与多线程的解决办法. 如何处理线程的异常. 7.1 线程的状态 线程对象在不同的运行时期有不 ...