Mysterious UnsatisfiedLinkError

As I said a while back, I haven't done any java since 1.1, and a lot has changed. However, I thought I understood how to set up native link paths, project dependencies, and libraries in Eclipse to get it all working. And, indeed, I have lwjgl working just fine from my own project (when exported from jme), as an example.



However, when adding the jmephysics project from CVS to my Eclipse workspace, adding the project to my own project, and setting a native library path of jmephysics/impl/ode/lib, I still get an UnsatisfiedLinkError exception when starting a project using jmephysics/odejava. I'm actually only trying to use the odejava part of it, as my physics entities shouldn't be graphical Nodes.



I also tried downloading odejava and using it directly, but that had the same problem.



In my own project, Java Build Path, Libraries, I've added odejava-jne.jar with a Native library location of jmephysics/impl/ode/lib. Additionally, among Projects, I've added jmephysics as a dependency. It also has a native library path of jmephysics/impl/ode/lib. Inside the jmephysics library, I've set up an export of odejava-jne.jar in addition to the default exporrts (this seems a little redundant, but I'm grasping for straws here).



Curiously, when I run the Tutorial example projects in the jmephysics project, it works.



I'm assuming it's the native library that's the problem, but I guess I could be wrong. What else am I missing?




java.lang.UnsatisfiedLinkError: org.odejava.ode.OdeJNI.dWorldCreate()J
   at org.odejava.ode.OdeJNI.dWorldCreate(Native Method)
   at org.odejava.ode.Ode.dWorldCreate(Ode.java:620)
   at org.odejava.World.<init>(World.java:116)


I believe I have satisfied that requirement using the process I outlined above. Note that the tutorial actually says "unknown" and "fixme – doesn't work for author" in that region.



I tried adding joode and junit jars to the export path as well, but that didn't help. Note that the unsatisfied link error symbol is the wrapping version of dWorldCreate(), which should already be in odejava-jne.jar, which is referenced.

Have you seen the instructions here:

http://www.jmonkeyengine.com/wiki/doku.php?id=setting_up_eclipse_to_build_jme-physics



Specifically look at “Using jMEphysics2 in Your Project”.

Are you running your application with the following JVM argument?



-Djava.library.path=…/jme/lib/;…/jmephysics/impl/ode/lib



I believe that if you set the Native library path it should work, but maybe depends on the way you launch the application.



Just give it a try. In Eclipse, you should write that (check paths) under the VM arguments section on the Run configuration.


It is my belief I shouldn't need to do that, because Eclipse already lets you specify native paths for running. After all, it finds its way to the lwjgl that's in jME, using the Native path specified for that JAR. I have specified the same kind of native path for the jMEPhysics dependencies, but they don't seem to work, somehow. Or maybe the DLL that comes with JME actually isn't exporting the function in question or something…



Note that the jMEPhysics project itself also only uses Native Path references from the project, and doesn't specify a path for the VM.

I tried just adding a System.loadLibrary("odejava") at the beginning of my main(), and then it works.

Apparently, neither odejava or jmephysics have a static block to make that happen automatically?

This is not mentioned in the documentation I've seem (but then, odejava.org was down when I checked).

hmm i use eclipse too and in the jmephysics project i didn't specify a native path at all.

i only did it for lwjgl.jar

Had to specify a path for lwjgl and ode in the style jjmontes posted, a -D property in the VM args for the eclipse launch config.



There is no need for the call to made from a static context. It should work from anywhere. the only way it should be able to work in one place and not another is if you are using different classloaders.



So, when you say 'works', do you mean the whole app now, or just the first call to System.loadLibrary(…) ?

What I'm saying is that if I'm calling System.loadLibrary() before I create the ODE World object, I don't get an unsatisfied link error. That was surprising to me, because I thought odejava would for sure make that call during static start-up so that the user doesn't have to worry about it. I couldn't check the documentation for odejava, though, because the site was down at the time (as reported in another thread).



Now it works. I don't need to specify any VM args, because all the necessary paths are arguments to the libraries/projects in the Eclipse set-up. It wasn't a path problem at all; it was a usage problem.

The message you posted means that you were able to load a native library named 'odejava' (as you already figured - loadLibrary succeeded). Ususally a message like that (complaining about a specific missing function) means that you either have a mismatch between the java library and the native library (java declares more/other functions than the native lib exports), or some delay-loaded libraries are missing for the native. Though ODEJava checks that the versions match (native version number vs. expected version number in java, see static block in Odejava.java) and the dWorldCreate function did not change for a long time.



As you have a working java app, I'd recommend to check things like:

0. Does your working app actually call that function? (I think it should be)

  1. Is the same java library version used (odejava-jni.jar).
  2. Is the same native library used ((lib)odejava.dll/so/jnilib) - same OS? Which one, btw?
  3. Are the required libraries found or is the PATH variable and the working directory the same.
  4. Does the static block of Odejava execute? What is returned by getLibraryVersion()?

@Irrisor,



I got that message before I added the System.loadLibrary() call. System.loadLibrary() fixed the problem. The problem was that I assumed that odejava would call System.loadLibrary() automatically, for example within a static block. Apparently, it doesn't, and you have to call it yourself. Problem solved. Thanks for helping, though!

jwatte, the exception is thrown from INSIDE the System.loadLibrary call, so how can it not be called?



As to 'static initialiser block', why? The ONLY thing that makes a difference when calling loadLibrary is the classloader, so it makes no sense that calling it first would fix it.



There is no need to call it yourself.



What irrisor said - does the static block execute?

I don't see the class loader on the stack when looking at that exception. Look at the stack trace I posted in the first message:


java.lang.UnsatisfiedLinkError: org.odejava.ode.OdeJNI.dWorldCreate()J
at org.odejava.ode.OdeJNI.dWorldCreate(Native Method)
at org.odejava.ode.Ode.dWorldCreate(Ode.java:620)
at org.odejava.World.<init>(World.java:116)


It looks to me as if it's trying to late-bind the OdeJNI.dWorldCreate function (native), and can't find it, and at that point, it throws an UnsatisfiedLinkError.

Just adding the call to System.loadLibrary() in my main(), or in a static block in my main class, makes it work. And, yes, the block I add gets executed in my class.
jwatte said:

And, yes, the block I add gets executed in my class.

umm, we were talking about the static block in Odejava.java. It loads the native library itself - does it get executed? If yes, why do you need to load the library again/prior to that? If no - why not?!

At the time, I couldn't check the static block in odejava, because the web site was down. At this point, I've worked around it, and just spent 2 days re-building a machine around Vista 64, so I'm not keen on going back to re-check…