gpt4 book ai didi

java - native 库在某些 JVM 上工作不正常

转载 作者:行者123 更新时间:2023-12-04 08:35:54 26 4
gpt4 key购买 nike

我正在尝试使用 JNA 在 Java 中使用 native 库。库加载,我可以调用方法,但在某些 JVM 发行版上, native 库的行为不符合预期。一些结果:

JDK distributions              Behaves as expected
Oracle JDK 1.8.0_191 yes
Liberica JDK 1.8u192 no
Liberica JDK 1.8u275 no
AdoptOpenJDK OpenJ9 1.8u272 yes
AdoptOpenJDK OpenJ9 15.0.1 no
AdoptOpenJDK Hotspot 1.8u275 no
AdoptOpenJDK Hotspot 14.0.1 no
这里预期的行为正在通过 LC_get_hardware_info 获取硬件信息然后退出没有错误。
似乎没有 JDK9+ 发行版可以工作,一些 JDK8 发行版可以工作,有些则不能(编辑)所有经过测试的 JVM 都是 64 位的。
代码(编辑:不调用 LC_get_hardware_info 不会改变行为,只是在成功的情况下没有输出),由 SenseLC 返回的值是错误代码:
public static void main(String[] args) {        
System.setProperty("jna.library.path", System.getProperty("user.dir"));

SenseLC lib = SenseLC.INSTANCE;

PointerByReference handle = new PointerByReference(new Memory(8));

int ret = lib.LC_open(0, 0, handle);
if (ret != SenseLC.LC_SUCCESS) {
System.out.println("Open: " + SenseLCUtil.getCodeName(ret));
return;
}
System.out.println("Handle: " + handle.getValue());

LC_hardware_info hi = new LC_hardware_info();
ret = lib.LC_get_hardware_info(handle.getValue(), hi);
if (ret != SenseLC.LC_SUCCESS) {
System.out.println("Read: " + SenseLCUtil.getCodeName(ret));
return;
}

System.out.println(hi);

ret = lib.LC_close(handle.getValue());
if (ret != SenseLC.LC_SUCCESS) {
System.out.println("Close: " + SenseLCUtil.getCodeName(ret));
return;
}

}
SenseLCUtil.getCodeName只是将返回码映射到字符串
预期行为:
所有调用 SenseLC返回 0 ( LC_SUCCESS ),在调用 ret = lib.LC_get_hardware_info(handle.getValue(), hi); 之后, System.out.println(hi);打印:
LC_hardware_info{
developerNumber={somenumber}
serialNumber={somenumber}
setDate={somenumber}
reservation=0
}
故障行为:
调用 int ret = lib.LC_open(0, 0, handle);成功(调用后 ret=0),然后运行后 ret = lib.LC_get_hardware_info(handle.getValue(), hi); ret=3 ( LC_INVALID_PARAMETER ),程序输出为:
Read: LC_INVALID_PARAMETER
在某些 JDK 上,似乎从 native 代码返回了不正确的句柄。
编辑 1 : 添加了 LC_hardware_info 和 SenseLC 类
LC_hardware_info:
@FieldOrder({
"developerNumber",
"serialNumber",
"setDate",
"reservation"
})
public class LC_hardware_info extends Structure {

public int developerNumber;
public byte[] serialNumber = new byte[8];
public int setDate;
public Pointer reservation;

public String getSerial() {
return new String(serialNumber, StandardCharsets.UTF_8);
}

@Override
public String toString() {
return "LC_hardware_info{"
+ "\ndeveloperNumber=" + developerNumber
+ "\nserialNumber=" + getSerial()
+ "\nsetDate=" + setDate
+ "\nreservation=" + reservation
+ "\n}";
}

}
感应LC:
public interface SenseLC extends Library {

int LC_SUCCESS = 0; // Successful
int LC_OPEN_DEVICE_FAILED = 1; // Open device failed
int LC_FIND_DEVICE_FAILED = 2; // No matching device was found

int LC_INVALID_PARAMETER = 3; // Parameter Error
int LC_INVALID_BLOCK_NUMBER = 4; // Block Error
int LC_HARDWARE_COMMUNICATE_ERROR = 5; // Communication error with hardware
int LC_INVALID_PASSWORD = 6; // Invalid Password
int LC_ACCESS_DENIED = 7; // No privileges
int LC_ALREADY_OPENED = 8; // Device is open
int LC_ALLOCATE_MEMORY_FAILED = 9; // Allocate memory failed
int LC_INVALID_UPDATE_PACKAGE = 10; // Invalid update package
int LC_SYN_ERROR = 11; // thread Synchronization error
int LC_OTHER_ERROR = 12; // Other unknown exceptions

SenseLC INSTANCE = (SenseLC) Native.load("Sense_LC", SenseLC.class);

int LC_open(int vendor, int index, PointerByReference handle);
int LC_close(Pointer handle);
int LC_passwd(Pointer handle, int type, byte[] passwd);
int LC_read(Pointer handle, int block, byte[] buffer);
int LC_write(Pointer handle, int block, byte[] buffer);
int LC_encrypt(Pointer handle, byte[] plaintext, byte[] ciphertext);
int LC_decrypt(Pointer handle, byte[] ciphertext, byte[] plaintext);
int LC_set_passwd(Pointer handle, int type, byte[] passwd, int retries);
int LC_change_passwd(Pointer handle, int type, byte[] oldpasswd, byte[] newpasswd);
int LC_get_hardware_info(Pointer handle, LC_hardware_info info);
int LC_get_software_info(LC_software_info info);
int LC_Hmac(Pointer handle, byte[] text, int textlen, byte[] digest);
int LC_Hmac_software(byte[] text, int textlen, byte[] key, byte[] digest);
int LC_update(Pointer handle, byte[] buffer);
int LC_set_key(Pointer handle, int type, byte[] key);
int LC_gen_update_pkg(byte[] serial, int block, byte[] buffer, byte[] key, byte[] uptPkg);

}
编辑 2 库头:
lc.h ,部分 sdk (Clave2)
编辑 3 :
更新了 JNA 映射,问题仍然存在。旧代码可以找到 here

最佳答案

您在不同 JVM 上得到不同结果的事实表明存在未定义的行为。在它看起来有效的情况下,你只是很幸运。
正如评论中所讨论的,您的问题很可能是 lc_handle_t 的映射。 .头文件表明它是 64 位机器上的指针大小,int 32 位机器上的大小。所以你应该使用 PointerByReference当你看到 * lc_handle_t (打开拿到 Handlebars 时)然后用getValue()在返回的句柄上用于 lc_handle_t 的其他用途.
该类型也出现在 reservation 中您的领域LC_hardware_info结构,应该映射到 Pointer .

关于java - native 库在某些 JVM 上工作不正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64801123/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com