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) | Buffer Pointer |
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函数. 对于那些可 ...
随机推荐
- 正则表达式(RegEx)官方手册/权威指南【Python】
前言 正则表达式(称为RE,或正则,或正则表达式模式)本质上是嵌入在Python中的一种微小的.高度专业化的编程语言,可通过 re 模块获得. 使用这种小语言,你可以为要匹配的可能字符串集指定规则:此 ...
- Python——Scrapy爬取链家网站所有房源信息
用scrapy爬取链家全国以上房源分类的信息: 路径: items.py # -*- coding: utf-8 -*- # Define here the models for your scrap ...
- element ui DatePicker 禁用当前日之前的时间
<el-date-picker style="width:195px" value-format="yyyy-MM-dd" v-model="f ...
- css的尺寸、display的属性、以及浮动和清除浮动的方法
css的尺寸width heightline-height 行高是由三部分构成,上间距 文本高度 下间距,且上下间距相等.所以文字居中.行高:一旦设置了行高,元素内部必须有内容.line-height ...
- js,获取字符串中存在中文的个数
var RespMemo='1231231617440C01 心存正义 10'; //定义字符串 re = /[\u4E00-\u9FA5]/g; //测试中文字符的正则 var ...
- C# 连接数据操作的时候抛异常,连接超时
先说说我的业务.我在发送优惠券的时候,同时给6千多个会员发送优惠券,执行了update 和insert语句,这写语句都是通过字符串拼接而来的.update和insert语句加起来一共是一万多条语句.在 ...
- MySQL Execution Plan--使用Query Rewrite
安装Query Rewrite Plugin 在MySQL的安装目录的share文件夹下,有两个文件用来安装和卸载Query Rewrite Plugin: install_rewriter.sql: ...
- (原+修改)Pip使用国内源安装opencv
转载请注明出处: https://www.cnblogs.com/darkknightzh/p/12000823.html 参考网址: https://www.imooc.com/article/34 ...
- eclipse 将原工作空间配置导入新建工作空间
相信各位小伙伴使用eclipse开发的时候经常会遇到新建工作空间的时候, 但是每次新建工作空间之后都要重新配置空间.安装插件等等 笔者曾经对此问题很是绝望. . . 后发现新建的工作空间可以导入其他工 ...
- Mysql数据库之慢查询
一.简介 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能. 二.参数说明 slow_query_log 慢查询开启状态 slow_ ...