java.lang.UnsatisfiedLinkError: libjawt.so

30 views
Skip to first unread message

David Robison

unread,
Nov 16, 2021, 3:28:17 PM11/16/21
to Java Native Access
I'm running on Ubuntu 20.04 with openjdk-11. When I try to get the component id of a window, I get the following error:

java.lang.UnsatisfiedLinkError: libjawt.so: cannot open shared object file: No such file or directory
at com.sun.jna.Native.getWindowHandle0(Native Method) ~[jna-5.5.0.jar:5.5.0 (b0)]
at com.sun.jna.Native$AWT.getComponentID(Native.java:2359) ~[jna-5.5.0.jar:5.5.0 (b0)]
at com.sun.jna.Native.getComponentID(Native.java:326) ~[jna-5.5.0.jar:5.5.0 (b0)]

However, I've verified that the file does exist. I also tried adding its location to the jna.library.path and still get this error. Any idea what I may be doing wrong or how to debug this further?

Thanks, David

Neil C Smith

unread,
Nov 17, 2021, 12:11:16 PM11/17/21
to jna-...@googlegroups.com
On Tue, 16 Nov 2021 at 20:28, David Robison <kc7b...@gmail.com> wrote:
> I'm running on Ubuntu 20.04 with openjdk-11. When I try to get the component id of a window, I get the following error:
>
> java.lang.UnsatisfiedLinkError: libjawt.so: cannot open shared object file: No such file or directory

Is that with Ubuntu's OpenJDK? If so, try with another OpenJDK
provider. There are some weird linking bugs with the Ubuntu / Debian
OpenJDK packages. Have seen that one before.

Best wishes,

Neil

--
Neil C Smith
Codelerity Ltd.
www.codelerity.com

Codelerity Ltd. is a company registered in England and Wales
Registered company number : 12063669
Registered office address : Office 4 219 Kensington High Street,
Kensington, London, England, W8 6BD

David Robison

unread,
Nov 17, 2021, 12:15:56 PM11/17/21
to jna-...@googlegroups.com
This is with Ubuntu's OpenJDK and OpenJFX
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Java Native Access" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/jna-users/h1WyVnq2vUQ/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> jna-users+...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/jna-users/CAPxOS5HRJ75029daWC0VUs7tbE%3D1DDk8ikq%2BsnS_NkAZ79ge3w%40mail.gmail.com.
>

Matthias Bläsing

unread,
Nov 17, 2021, 1:07:37 PM11/17/21
to jna-...@googlegroups.com
Hi David,
I don't know, what is the difference between the system JDK and the
regular OpenJDK build, but there is a work around. This works on
regular OpenJDK and the Ubuntu JDK:

public class JNAGetWindowHandle {
public static void main(String[] args) {
System.loadLibrary("jawt"); // This is the core step
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setSize(800, 600);
frame.setVisible(true);
System.out.println(Native.getWindowID(frame));
});
}
}

Something in the Ubuntu JDK is different, that jawt is not loaded
always.

HTH

Matthias

David Robison

unread,
Nov 17, 2021, 1:35:43 PM11/17/21
to jna-...@googlegroups.com
It turns out that I had to set LD_LIBRARY_PATH environmental variable,
not the jna.library.path. Thanks, David
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Java Native Access" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/jna-users/h1WyVnq2vUQ/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> jna-users+...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/jna-users/87bb5db824072393232f5f37b85166e47e3fc2bf.camel%40doppel-helix.eu.
>

Neil C Smith

unread,
Nov 18, 2021, 10:35:15 AM11/18/21
to jna-...@googlegroups.com
On Wed, 17 Nov 2021 at 18:07, Matthias Bläsing
<mbla...@doppel-helix.eu> wrote:
> I don't know, what is the difference between the system JDK and the
> regular OpenJDK build, but there is a work around. This works on
> regular OpenJDK and the Ubuntu JDK:
...
> System.loadLibrary("jawt"); // This is the core step
...
> Something in the Ubuntu JDK is different, that jawt is not loaded
> always.

Well, libjawt is loaded on demand isn't it? So, not until JNA tries
to load it. And JNA can't find it. Also fails with Native.load(..)
incidentally, which works with a non-distro JDK.

I'm curious whether that's a bug in JNA or in the distro JDK. It's
not a bug specific to JNA though.

David Robison

unread,
Nov 18, 2021, 10:36:34 AM11/18/21
to jna-...@googlegroups.com
It appears that I had to add the path to libjawt.so to the
LD_LIBRARY_PATH and not the jna.library.path system property. Doing
this make it work. TNX
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Java Native Access" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/jna-users/h1WyVnq2vUQ/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> jna-users+...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/jna-users/CAPxOS5F2NZgTqSqYHDbCi2Wu8CJU8oS-XcQsp%3DjO_j9WRWZhGQ%40mail.gmail.com.
>

Neil C Smith

unread,
Nov 22, 2021, 4:58:39 AM11/22/21
to jna-...@googlegroups.com
On Thu, 18 Nov 2021 at 15:36, David Robison <kc7b...@gmail.com> wrote:
> It appears that I had to add the path to libjawt.so to the
> LD_LIBRARY_PATH and not the jna.library.path system property. Doing
> this make it work. TNX

Yes, that's a workaround. Although I'd probably prefer the more
targetted System.loadLibrary one Matthias mentioned rather than using
LD_LIBRARY_PATH.

My comments were aimed more at Matthias' reply and JNA in general.
This should probably work out of the box. I wondered where he thinks
the bug really lies - JNA or distro package?

Options might be to use System.loadLibrary (for Linux only) at -

https://github.com/java-native-access/jna/blob/master/src/com/sun/jna/Native.java#L2411

Or to use absolute paths, as for Windows, at -

https://github.com/java-native-access/jna/blob/master/native/dispatch.c#L3101

???

Tres Finocchiaro

unread,
Nov 23, 2021, 11:41:12 AM11/23/21
to jna-...@googlegroups.com
If you know the dll/so/dylib is located relative to your Java Home, you can use System.getProperty("java.home") and append "bin", etc and then set (or append it) to what JNA searches for.

I too would recommend manipulating the JNA search path using jna.library.path.  If this doesn't work, it is likely due to dependent libraries that can't be found.  Make sure to add dependent libraries to this path too.  The error you receive is slightly different if the library can't be found versus the library can't be loaded due to missing dependencies.

In regards to Ubuntu's Java not working, the "alternatives" method that Ubuntu uses trusts symlinks for path resolution, so make sure to echo your paths before making any assumptions that they're correct.

For example, on Ubuntu 20.04, "java" is NEVER located at "/usr/bin/java" but rather, this is a symlink to a symlink to the actual java.  Take the following:

ubuntu@ubuntu:~$ which java
/usr/bin/java

ubuntu@ubuntu:~$ readlink $(which java)
/etc/alternatives/java

ubuntu@ubuntu:~$ readlink $(readlink $(which java))
/usr/lib/jvm/java-11-openjdk-arm64/bin/java


This should not impact the value of "java.home", but it is good to know when manipulating search paths on a filesystem that uses symlinks.

In regards to where these are located, it may vary... for example, with Ubuntu's Java 11 running on ARM64, the jawt is in a special aarch64 directory.

/usr/lib/jvm/java-8-openjdk-arm64/jre/lib/aarch64/libjawt.so
/usr/lib/jvm/java-8-openjdk-arm64/lib/aarch64/libjawt.so


On the other hand, Java 11 has this in the standard lib directory:

/usr/lib/jvm/java-11-openjdk-arm64/lib/libjawt.so

To list the dependant libraries:

ldd /usr/lib/jvm/java-11-openjdk-arm64/lib/libjawt.so

In my case, Ubuntu complains with the following:

libjvm.so => not found

So, in addition to the libjawt.so directory, I would also add the libjvm.so to the search path.  For Java 11 on ARM64, it's here:

/usr/lib/jvm/java-11-openjdk-arm64/lib/server/libjvm.so

For Java 8 on ARM64 it's here:

/usr/lib/jvm/java-8-openjdk-arm64/jre/lib/aarch64/server/libjvm.so

These values will change slightly for Intel-based Ubuntu versions, however if all paths are resolved, I would expect the library to load just fine.

-Tres

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/CAPxOS5HSTTcUs38Sje30BtB5D%3D%3DuW%3DXpaJNJ6GofyUOd738r2g%40mail.gmail.com.

Tres Finocchiaro

unread,
Nov 23, 2021, 11:46:33 AM11/23/21
to jna-...@googlegroups.com
(Resending with ** corrections)

If you know the dll/so/dylib is located relative to your Java Home, you can use System.getProperty("java.home") and append ** "lib", "jre/lib", etc and then set (or append it) to what JNA searches for.

I too would recommend manipulating the JNA search path using jna.library.path.  If this doesn't work, it is likely due to dependent libraries that can't be found.  Make sure to add dependent libraries to this path too.  The error you receive is slightly different if the library can't be found versus the library can't be loaded due to missing dependencies.

In regards to Ubuntu's Java not working, the "alternatives" method that Ubuntu uses trusts symlinks for path resolution, so make sure to echo your paths before making any assumptions that they're correct.

For example, on Ubuntu 20.04, "java" is NEVER located at "/usr/bin/java" but rather, this is a symlink to a symlink to the actual java.  Take the following:

ubuntu@ubuntu:~$ which java
/usr/bin/java

ubuntu@ubuntu:~$ readlink $(which java)
/etc/alternatives/java

ubuntu@ubuntu:~$ readlink $(readlink $(which java))
/usr/lib/jvm/java-11-openjdk-arm64/bin/java


This should not impact the value of "java.home", but it is good to know when manipulating search paths on a filesystem that uses symlinks.

In regards to where these are located, it may vary... for example, with Ubuntu's Java 11 running on ARM64, the jawt is in a special aarch64 directory.

/usr/lib/jvm/java-8-openjdk-arm64/jre/lib/aarch64/libjawt.so
/usr/lib/jvm/java-8-openjdk-arm64/lib/aarch64/libjawt.so


On the other hand, Java 11 has this in the standard lib directory:

/usr/lib/jvm/java-11-openjdk-arm64/lib/libjawt.so

To list the dependant libraries:

ldd /usr/lib/jvm/java-11-openjdk-arm64/lib/libjawt.so

In my case, Ubuntu complains with the following:

libjvm.so => not found

So, in addition to the libjawt.so directory, I would also add the libjvm.so to the search path.  For ** Java 8 on ARM64, it's here:

Neil C Smith

unread,
Nov 23, 2021, 12:33:22 PM11/23/21
to jna-...@googlegroups.com
On Tue, 23 Nov 2021 at 16:41, Tres Finocchiaro
<tres.fin...@gmail.com> wrote:
> I too would recommend manipulating the JNA search path using jna.library.path. If this doesn't work, it is likely due to dependent libraries that can't be found.

It won't work because jna.library.path isn't used in this particular case.

> ldd /usr/lib/jvm/java-11-openjdk-arm64/lib/libjawt.so
>
> In my case, Ubuntu complains with the following:
>
> libjvm.so => not found

The working JDK says the same though.

One curious dlopen related difference I've found between the working
and non-working JDK's is that the working one (Adopt) seems to have
the relevant paths in DT_RPATH, while the non-working distro one has
in DR_RUNPATH. Could this be the cause of any difference?

Best wishes,

Neil

Matthias Bläsing

unread,
Nov 23, 2021, 2:20:53 PM11/23/21
to jna-...@googlegroups.com
Hi,
Wikipedia has to say:

The ld dynamic linker does not search DT_RUNPATH locations for
transitive dependencies, unlike DT_RPATH

And refers to this Ubuntu issue:

https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1253638

The TL;DR version:

RUNPATH definitions only apply to direct dependencies and RPATH applies
also to transitive dependencies.

There are more subtle differences, but it is the key point from my POV.

Testing can be done by following this stackoverflow answer:

https://stackoverflow.com/questions/13769141/can-i-change-rpath-in-an-already-compiled-binary

matthias@enterprise:~$ readelf -d /usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java | grep "R*PATH"
0x000000000000001d (RUNPATH) Bibliothek runpath: [$ORIGIN/../lib/jli:$ORIGIN/../lib]
matthias@enterprise:~$ sudo patchelf --remove-rpath /usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java
matthias@enterprise:~$ readelf -d /usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java | grep "R*PATH"
matthias@enterprise:~$ sudo patchelf --force-rpath --set-rpath '$ORIGIN/../lib/jli:$ORIGIN/../lib' /usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java
matthias@enterprise:~$ readelf -d /usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java | grep "R*PATH"
0x000000000000000f (RPATH) Bibliothek rpath: [$ORIGIN/../lib/jli:$ORIGIN/../lib]
matthias@enterprise:~$


This moves the RUNPATH to RPATH and in my tests this is enough to fix
the issue.

So this is my take on the situation:

- Native#getWindowHandle0 calls into the native object libjnidispatch.so
- libjnidispatch.so tries to load libjawt.so

so the loading object of libjawt.so is libjnidispatch.so and here comes
the difference between RPATH and RUNPATH into play.

RPATH comes from the java binary and thus points to the right directory
(for the Ubuntu JDK: /usr/lib/jvm/java-1.11.0-openjdk-
amd64/bin/../lib). It is transitive thus libjawt is found.

RUNPATH is not transitive and the calling binary is libjnidispatch.so.
This library has no RUNPATH and no RPATH set, so dl_open must find the
library by conventional means.

So IMHO the distribution build is broken. I think it is a reasonable
expectation, that I can load jawt in a headful environment without
jumping through hoops.

Greetings

Matthias

Neil C Smith

unread,
Nov 24, 2021, 7:04:11 AM11/24/21
to jna-...@googlegroups.com
Hi,

On Tue, 23 Nov 2021 at 19:20, Matthias Bläsing
<mbla...@doppel-helix.eu> wrote:
> Wikipedia has to say:
>
> The ld dynamic linker does not search DT_RUNPATH locations for
> transitive dependencies, unlike DT_RPATH
>
> And refers to this Ubuntu issue:
>
> https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1253638
...
> This moves the RUNPATH to RPATH and in my tests this is enough to fix
> the issue.

Thanks Matthias. I'd read that same Ubuntu issue, but not considered
trying to patchelf the binaries. Good to know that's the cause - seen
it a few times now.

But ...

> RUNPATH is not transitive and the calling binary is libjnidispatch.so.
> This library has no RUNPATH and no RPATH set, so dl_open must find the
> library by conventional means.
>
> So IMHO the distribution build is broken. I think it is a reasonable
> expectation, that I can load jawt in a headful environment without
> jumping through hoops.

Maybe, but distros seem to be moving to using RUNPATH rather than the
"deprecated???" RPATH. There are changes in JDK tests to support
both. This might break elsewhere in future.

Your comment also gave me a thought - why does System.loadLibrary(..)
work. It seems to first check in sun.boot.library.path.

Setting jna.library.path to sun.boot.library.path allows for loading
libjawt via Native.load(..) at least.

So, maybe JNA should really be looking to load libjawt via
sun.boot.library.path first for this?

Matthias Bläsing

unread,
Nov 24, 2021, 2:23:12 PM11/24/21
to jna-...@googlegroups.com
Hi,

Am Mittwoch, dem 24.11.2021 um 12:03 +0000 schrieb Neil C Smith:

> Your comment also gave me a thought - why does System.loadLibrary(..)
> work. It seems to first check in sun.boot.library.path.
>
> Setting jna.library.path to sun.boot.library.path allows for loading
> libjawt via Native.load(..) at least.
>
> So, maybe JNA should really be looking to load libjawt via
> sun.boot.library.path first for this?

jawt is loaded via dl_open in native code, so is not just a trivial
patch, but about two days of recompiling libraries (where at least only
architecture is currently not buildable).

I don't see me looking at this in the near future.

Greetings

Matthias

Neil C Smith

unread,
Nov 25, 2021, 4:09:49 AM11/25/21
to jna-...@googlegroups.com
On Wed, 24 Nov 2021 at 19:23, Matthias Bläsing
<mbla...@doppel-helix.eu> wrote:
> Am Mittwoch, dem 24.11.2021 um 12:03 +0000 schrieb Neil C Smith:
>
> > Your comment also gave me a thought - why does System.loadLibrary(..)
> > work. It seems to first check in sun.boot.library.path.
> >
> > Setting jna.library.path to sun.boot.library.path allows for loading
> > libjawt via Native.load(..) at least.
> >
> > So, maybe JNA should really be looking to load libjawt via
> > sun.boot.library.path first for this?
>
> jawt is loaded via dl_open in native code, so is not just a trivial
> patch, but about two days of recompiling libraries (where at least only
> architecture is currently not buildable).

Yes, I know, but I was considering fixing it elsewhere. I may have a
look at a potential PR - not this week until NetBeans is out! :-)

Like you, I thought this was the distro packaging at fault. Looking
deeper I'm no longer convinced that's the case.
Reply all
Reply to author
Forward
0 new messages