java.lang.UnsatisfiedLinkError with Java API bindings

Hello!

I succesfully installed client and server for windows from this link https://www.foundationdb.org/downloads/6.2.22/windows/installers/foundationdb-6.2.22-x64.msi
After it I checked fdbcli and it works fine.

But I have problem with Java API bindings. I copy simple example from https://apple.github.io/foundationdb/javadoc/index.html

package fdb;

import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.tuple.Tuple;

public class Example {
    public static void main(String[] args) {

        try {
            FDB fdb = FDB.selectAPIVersion(620);

            try (Database db = fdb.open()) {
                // Run an operation on the database
                db.run(tr -> {
                    tr.set(Tuple.from("hello").pack(), Tuple.from("world").pack());
                    return null;
                });

                // Get the value of 'hello' from the database
                String hello = db.run(tr -> {
                    byte[] result = tr.get(Tuple.from("hello").pack()).join();
                    return Tuple.fromBytes(result).getString(0);
                });

                System.out.println("Hello " + hello);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

But I have exception:

java.lang.UnsatisfiedLinkError: C:\Users\art17em\AppData\Local\Temp\fdbjni3285163144695489469.library: Can't find dependent libraries
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
	at java.lang.Runtime.load0(Runtime.java:809)
	at java.lang.System.load(System.java:1086)
	at com.apple.foundationdb.JNIUtil.loadLibrary(JNIUtil.java:106)
	at com.apple.foundationdb.FDB.<clinit>(FDB.java:99)
	at fdb.Example.main(Example.java:11)

OS: Windows 10

I tried 2 Java Dependency Versions:

<dependency>
     <groupId>org.foundationdb</groupId>
     <artifactId>fdb-java</artifactId>
     <version>6.3.1</version>
 </dependency>

and

<dependency>
     <groupId>org.foundationdb</groupId>
     <artifactId>fdb-java</artifactId>
     <version>6.2.22</version>
 </dependency>

Also I tried 2 different jdks: 1.8.0_181 and 11.0.7 but there is no any difference

I tried to debug-trace through the calling code and found that com.apple.foundationdb.JNIUtil#loadLibrary successfully copied the bundled /lib/windows/amd64/fdb_java.dll file in a temp location(C:\Users\art17em\AppData\Local\Temp\fdbjni3285163144695489469.library) and eventually calling System.load(filename); but the System.load() is failing with above exception.

Also I found strange code at com.apple.foundationdb.FDB

try {
	JNIUtil.loadLibrary("fdb_c");
} catch (Throwable t) {
	// EAT: this can be useful for loading on windows
}
JNIUtil.loadLibrary("fdb_java");

and noticed that loading of fdb_c library also failed for windows.

Can someone let me know what is going wrong?

The java bindings alone aren’t enough to connect to a cluster. They’re a wrapper around a c api that you can download here: https://www.foundationdb.org/downloads/6.2.22/windows/installers/foundationdb-6.2.22-x64.msi. Is it possible that you haven’t installed the c library?

Edit: I see now from your post that you installed that. In that case I’m not sure, sorry.

I’m not very familiar with debugging shared libraries on windows, but this stack overflow thread has some good suggestions and explanations of JNI search paths on Windows:

We would like to get to a root cause so that this is smoother in the future.

Thanks for your reply. I checked you link. It could helpful but I don’t know which dlls and search paths to these dlls I should fix.

Also today I got a little bit different stacktrace:

java.lang.UnsatisfiedLinkError: C:\Users\art17em\AppData\Local\Temp\fdbjni12487464082760794312.library:
The specified procedure could not be found
	at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
	at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2442)
	at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2498)
	at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2694)
	at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2627)
	at java.base/java.lang.Runtime.load0(Runtime.java:768)
	at java.base/java.lang.System.load(System.java:1834)
	at com.apple.foundationdb.JNIUtil.loadLibrary(JNIUtil.java:106)
	at com.apple.foundationdb.FDB.<clinit>(FDB.java:99)
	at fdb.Example.main(Example.java:11)

I found intresting thread java - UnsatisfiedLinkError: The specified procedure could not be found - Stack Overflow

The message “The specified procedure could not be found” for UnsatisfiedLinkError indicates that a function in the root dll or in a dependent dll could not be found. The most likely cause of this in a JNI situation is that the native JNI function is not exported correctly. But this can apparently happen if a dependent DLL is loaded and that DLL is missing a function required by its parent.

By way of example, we have a library named input.dll. The DLL search order is to always look in the application directory first and the PATH directories last. In the past, we always ran executables from the same directory as input.dll. However, there is another input.dll in the windows system directory (which is in the middle of the DLL search order). So when running this from a java applet, if I include the code described above in the applet, which causes input.dll to be loaded, it loads the input.dll from the system directory. Because our code is expecting certain functions in input.dll which aren’t there (because it’s a different DLL) the load fails with an error message about missing procedures. Not because the JNI functions are exported wrong, but because the wrong dependent DLL was loaded and it didn’t have the expected functions in it.

Maybe I faced with the same problem - name conflict with dll files. On my computer fdb_java.dll could load not expected dependent dll with the same name. But I don’t how to check my suggestion and fix it

I tried one of the previous versions

<dependency>
     <groupId>org.foundationdb</groupId>
     <artifactId>fdb-java</artifactId>
     <version>6.2.10</version>
 </dependency>

And it works fine.

I think that problem in 6.3.1 was in incompatible version fdb_java.dll from fdb-java.jar and fdb_c.dll from foundationdb\bin

It looks like there’s an old tool from Microsoft called “Dependency Walker” (depends.exe) that can tell you which files + symbols fdb_java.dll recursively depends on, along with a list of unresolved symbols. It has apparently fallen out of maintenance, though there’s an open source reimplementation of it here with some additional functionality:

I haven’t used any of these tools, so I can’t really recommend one over the other, but they claim to be able to help debug this sort of issue. (Also, it wouldn’t surprise me if Microsoft rolled this functionality into some other development tool.)

On windows platform.
You can find fdb_c.dll in the installation directory of FundationDb, such as “C:\ProgramFiles\foundationdb\bin”. Load the fdb_c.dll in you application, you can run it.