java-native-access/jna

java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class com.sun.jna.Native

elfprince13 opened this issue · 12 comments

I was testing some JNA code in Eclipse, and all seemed to be going well (i.e., my code was running correctly), and then suddenly this started popping up, and I can't figure out what is even causing this, let alone how to resolve it. Notice that the UnsatisfiedLinkError is originating in JNA itself, not in my code. This error pops up in the source code, but I have no idea why it would suddenly be triggered when it wasn't before. I'm running on linux-x86-64, and using the official JARs.

You may have different versions of JNA.

updateLastError doesn't exist since 4.0.

On Oct 10, 2013, at 3:47 PM, elfprince13 notifications@github.com wrote:

I was testing some JNA code in Eclipse, and all seemed to be going well (i.e., my code was running correctly), and then suddenly this started popping up, and I can't figure out what is even causing this, let alone how to resolve it. Notice that the UnsatisfiedLinkError is originating in JNA itself, not in my code. This error pops up in the source code, but I have no idea why it would suddenly be triggered when it wasn't before. I'm running on linux-x86-64, and using the official JARs.


Reply to this email directly or view it on GitHub.

Huh. I have no idea where it would be coming from. There is a copy of some older JNA on my system, but it is very definitely not part of the classpath I'm executing with. I guess I'll have to dig through my other library's dependencies and try to find it.

Classpath Helper (http://classpathhelper.sourceforge.net/) reports there are no conflicting versions of JNA in my classpath, and I've tried with both the prebuilt JARs linked to from the repository readme, and with checking it out and building from scratch.

Moreover, if I remove jna.jar and jna-native.jar from my classpath, I get NoClassDefErrors for com.sun.jna.Pointer, which strongly suggests that there is no other JNA being loaded.

And....just for good measure - the results of running grep jna with the output of executing my program with -verbose:class as a JVM argument.

[Loaded com.sun.jna.Pointer from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Memory from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Version from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Callback$UncaughtExceptionHandler from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native$8 from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native$1 from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native$5 from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Pointer$Opaque from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class com.sun.jna.Native
    at com.sun.jna.Native.initIDs(Native Method)
    at com.sun.jna.Native.<clinit>(Native.java:139)

All of those are loaded from the version I built from an up-to-date git checkout.

What about libraries using JNA? can you get a stack trace to see which library is attempting to use the outdated JNA method?

On Oct 15, 2013, at 4:53 PM, elfprince13 notifications@github.com wrote:

Classpath Helper (http://classpathhelper.sourceforge.net/) reports there are no conflicting versions of JNA in my classpath, and I've tried with both the prebuilt JARs linked to from the repository readme, and with checking it out and building from scratch.


Reply to this email directly or view it on GitHub.

This seems to imply that your system has a libjnispatch.so on it already. Try running with -Djna.nosys=true.

On Oct 15, 2013, at 5:13 PM, elfprince13 notifications@github.com wrote:

And....just for good measure - the results of running grep jna with the output of executing my program with -verbose:class as a JVM argument.

[Loaded com.sun.jna.Pointer from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Memory from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Version from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Callback$UncaughtExceptionHandler from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native$8 from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native$1 from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Native$5 from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
[Loaded com.sun.jna.Pointer$Opaque from file:/gpfs/main/home/tdickerson/FreeBuild/FreeBuildJ/shared-libs/jna/jna.jar]
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class com.sun.jna.Native
at com.sun.jna.Native.initIDs(Native Method)
at com.sun.jna.Native.(Native.java:139)

All of those are loaded from the version I built from an up-to-date git checkout.


Reply to this email directly or view it on GitHub.

-Djna.nosys=true seems to have done the trick. May I ask how you inferred that from the log?

Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class com.sun.jna.Native
at com.sun.jna.Native.initIDs(Native Method)
at com.sun.jna.Native.(Native.java:139)

initIDs is a native method of the Native class which looks up and caches all the JNI bits like method IDs, class references and such. "updateLastError" would have been one of the methods looked up by the (old) native code; since "updateLastError" is no longer referenced in the current codebase (Java or native), it followed that some older native code must be running.

On Oct 16, 2013, at 1:56 PM, elfprince13 notifications@github.com wrote:

-Djna.nosys=true seems to have done the trick. May I ask how you inferred that from the log?


Reply to this email directly or view it on GitHub.

I had this problem today (I am a totally newbie in JNA).

It seems that the libjnidispatch.so for Linux x86-64, packaged in the jar is not the correct one.

I downloaded the JNA 4.0 jars (from https://github.com/twall/jna#download ) and followed some tutorials. But it didn't work because of this problem ( java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class).

So, I cloned the git repo, and started searching through the code.
I see that initIDs is a native code, declared in Native.java, and that the actual code is in native/dispatch.c (Java_com_sun_jna_Native_initIDs). Then I started to look if there was any .so in the jna-4.0.0.jar.
There was. I copied /com/sun/jna/linux-x86-64/libjnidispatch.so to my /usr/lib/ and it didn't worked (same error).

Then I compiled all the source code (with ant), and them searched for generated libjnidispatch.so (there are many). I copied the file build/native-linux-x86-64/libjnidispatch.so to my /usr/lib and the problem was gone. ( /usr/lib is in my LD_LIBRARY_PATH )

Pass "-Djna.nosys=true" to your VM on launch. Your system has an older version of JNA installed and is attempting to use that. Ordinarily JNA will detect the mismatch and complain, but apparently that functionality is not working in this case.

On Oct 22, 2013, at 2:49 PM, Luis Cardozo notifications@github.com wrote:

I had this problem today (I am a totally newbie in JNA).

It seems that the libjnidispatch.so for Linux x86-64, packaged in the jar is not the correct one.

I downloaded the JNA 4.0 jars (from https://github.com/twall/jna#download ) and followed some tutorials. But it didn't work because of this problem ( java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class).

So, I cloned the git repo, and started searching through the code.
I see that initIDs is a native code, declared in Native.java, and that the actual code is in native/dispatch.c (Java_com_sun_jna_Native_initIDs). Then I started to look if there was any .so in the jna-4.0.0.jar.
There was. I copied /com/sun/jna/linux-x86-64/libjnidispatch.so to my /usr/lib/ and it didn't worked (same error).

Then I compiled all the source code (with ant), and them searched for generated libjnidispatch.so (there are many). I copied the file build/native-linux-x86-64/libjnidispatch.so to my /usr/lib and the problem was gone. ( /usr/lib is in my LD_LIBRARY_PATH )


Reply to this email directly or view it on GitHub.

Ok, so on windows of course the search path is a little bit more prolific than LD_LIBRARY_PATH on linux. Today we started seeing licensing errors. The issue turned out to be that somebody else's jnidispatch.dll had ended up on the systems PATH variable, getting it loaded preferentially to the jar-unboxing that we had (unbeknownst to us) been using up until that point.

My quick fix was to simply open our version of JNA.jar under 7zip and put the binaries for jna for our target platforms (windows & linux x86) in the same ourApp/lib folder as the jna.jar. This gets it ranked higher in a windows system search and gets us on the LD_LIBRARY_PATH.

I didn't like the idea of simply saying 'don't ask the system loader for the jar' because I'd really like all of our native code to be loaded through the same mechanism, rather than have some be included in the lib folder and some be extracted to temporary directories.

The only documentation I can find from JNA on this issue was from the javadoc in /com/sun/jna/overview.html:

Loading JNA

JNA includes a small, platform-specific shared library which enables all native access. When the com.sun.jna.Native class is first accessed, JNA will first attempt to load this library from the directories specified in jna.boot.library.path. If that fails, it will fall back to loading from the system library paths. Finally it will attempt to extract the stub library from from the JNA jar file, and load it.

The jna.boot.library.path property is mainly to support jna.jar being included in -Xbootclasspath, where java.library.path and LD_LIBRARY_PATH are ignored. It is also useful for designating a version of the library to use in preference to any which may already be installed on the system.

Loading from the system may be disabled by jna.nosys=true, and unpacking from the jar file may be disabled by jna.nounpack=true.

The library name used to search for JNA's native library may be altered by setting jna.boot.library.name, which defaults to "jnidispatch". It may be useful to set this value if your system requires unique names for shared libraries (rather than unique paths), or if your system must store different versions of the JNA shared library (e.g. for different architectures) in the same directory.

markdown added by me for clarity

Long story short:

  • if you want to use the system lib loader then you want to make sure the relevant jnidisatch.dll/so files are in a high-ranking place in your systems search strategy.
  • If you want to use java's own "extract the native code from the jna.jar file and run that" then i cant think of a reason not to use -Djna.nosys=true