java JNA使用Unix状态导致UnsatisfiedLink异常

frebpwbc  于 2023-02-20  发布在  Java
关注(0)|答案(2)|浏览(137)

我尝试调用Linux的C-stat函数.
我的JNA代码:

public int stat(bap path, bap statdump);

BAP类:

public static class bap extends Structure {

    public byte[] array;

    public bap(int size) {
        array = new byte[size];
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"array"});
    }

}

虽然很麻烦,但它可以成功地作为许多其他函数的字节数组指针。我认为问题在于:int stat(const char *restrict path, struct stat *restrict buf);,由http://linux.die.net/man/3/stat定义
我如何传递一个常量字符数组,* restricted是什么意思?我试着用google搜索,但我不认为它喜欢搜索查询中的 *,因为没有相关的内容。
EDIT:完整异常

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:      43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.UnsatisfiedLinkError: Error looking up function 'stat': java: undefined       symbol: stat
    at com.sun.jna.Function.<init>(Function.java:208)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:536)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:513)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:499)
    at com.sun.jna.Library$Handler.invoke(Library.java:199)
    at com.sun.proxy.$Proxy0.stat(Unknown Source)
8iwquhpp

8iwquhpp1#

您是否查看过sys/stat.h,以确定是否存在stat()的实际声明,或者它是否是一个C预处理器宏?
在上面的链接中,如果定义了__USE_FILE_OFFSET64,则stat实际上就是stat64
要查看这是否是您的问题,只需将函数名从stat更改为stat64
作为一个更持久的解决方案,请为库加载提供function mapper
下面的示例首先查找基本标签,然后在追加“64”后重试:

FunctionMapper mapper = new FunctionMapper() {
    public String getFunctionName(NativeLibrary library, java.lang.reflect.Method method) {
        String name = method.getName();
        try {
            library.getFunction(name);
        } catch(UnsatisfiedLinkError e) {
            try {
                library.getFunction(name + "64");
                return name + "64";
            } catch(UnsatisfiedLinkError e) {
                 // If neither variant worked, report failure on the base label
            }
        }
        return name;
    }
};
Map options = new HashMap() {
    { put(Library.OPTION_FUNCTION_MAPPER, mapper); }
};
library = Native.loadLibrary("c", options);
y53ybaqx

y53ybaqx2#

也有可能stat函数在您安装的libc版本上不存在,就像我遇到的那样。
stat函数在使用GLIBC 2.31Debian 11.6上不存在,但在使用GLIBC 2.35Ubuntu 22.04上存在。
但是libc stat函数只是syscall4的 Package 器,因此您可以使用以下代码通过syscall函数调用stat

public interface Libc extends Library {

  Stats INSTANCE = Native.loadLibrary(Platform.C_LIBRARY_NAME, Libc.class);

  default int stat0(String pathname, Stat statbuf){
    return this.syscall(4, pathname, statbuf);
  }

  int syscall(int number, Object... args);

}

如果您感兴趣,完整代码为hosted here

    • 调试**

Debian 11.6版本

$ strings /lib/x86_64-linux-gnu/libc.so.6  | grep 'GNU C Library'
GNU C Library (Debian GLIBC 2.31-13+deb11u5) stable release version 2.31.

$ nm -D /lib/x86_64-linux-gnu/libc.so.6  | grep ' stat'
00000000000ec1c0 W statfs@@GLIBC_2.2.5
00000000000ec1c0 W statfs64@@GLIBC_2.2.5
00000000000ec220 W statvfs@@GLIBC_2.2.5
00000000000ec220 W statvfs64@@GLIBC_2.2.5
00000000000ec040 T statx@@GLIBC_2.28

Ubuntu 22.02

$ strings /lib/x86_64-linux-gnu/libc.so.6  | grep 'GNU C Library'
GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.1) stable release version 2.35.

$ nm -D /lib/x86_64-linux-gnu/libc.so.6  | grep ' stat'
0000000000113e60 W stat@@GLIBC_2.33
0000000000113e60 W stat64@@GLIBC_2.33
00000000001142b0 W statfs@@GLIBC_2.2.5
00000000001142b0 W statfs64@@GLIBC_2.2.5
0000000000114310 W statvfs@@GLIBC_2.2.5
0000000000114310 W statvfs64@@GLIBC_2.2.5
00000000001141e0 T statx@@GLIBC_2.28

相关问题