Search code examples
javaclinuxjava-native-interfacejna

JNA causes UnsatisfiedLinkException with Unix Stat


So, I'm attempting to call the Linux C - stat function.

My JNA code:

    public int stat(bap path, bap statdump);

the bap class:

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"});
    }

}

Which, while nasty, performs as a byte array pointer for many other functions successfully. What I think the problem is, is here: int stat(const char *restrict path, struct stat *restrict buf);, as defined by http://linux.die.net/man/3/stat

How do I pass a constant char array, and what does the *restrict mean? I attempted to google, but I don't think it liked * in the search query, as nothing was relevant.

EDIT: full exception

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)

Solution

  • Have you looked at sys/stat.h to see if there's an actual declaration for stat() or if it's a C preprocessor macro?

    In the link above, stat will actually be stat64 if __USE_FILE_OFFSET64 is defined.

    To see if this is your problem, simply change the function name from stat to stat64.

    As a more permanent solution supply a function mapper to your library load.

    The following example first looks up the base label, then tries again after appending "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);