Running my Java application with this code:
if (Desktop.isDesktopSupported())
{
Desktop d = Desktop.getDesktop();
try
{
d.browse(new URI("someurl")); // someurl is just an example, I am opening real url
}
catch (IOException | URISyntaxException e)
{
logger.warn(ExceptionUtils.getStackTrace(e));
}
}
results in application not responding (probably deadlock) on Manjaro Linux KDE. While it works with no problem on Windows, I do not want to check for OS in my application and allow it just for Windows. I have not tried other platforms yet.
What i use:
Detailed deadlock location:
Desktop
class:
public void browse(URI uri) throws IOException {
checkAWTPermission();
checkExec();
checkActionSupport(Action.BROWSE);
Objects.requireNonNull(uri);
peer.browse(uri); // <- goes here
}
Deadlock happens in XDesktopPeer
class that implements DesktopPeer
interface (peer) on method gnome_url_show(...)
:
private void launch(URI uri) throws IOException {
byte[] uriByteArray = ( uri.toString() + '\0' ).getBytes();
boolean result = false;
XToolkit.awtLock();
try {
if (!nativeLibraryLoaded) {
throw new IOException("Failed to load native libraries.");
}
result = gnome_url_show(uriByteArray); // <- deadlock / app not responding here
} finally {
XToolkit.awtUnlock();
}
if (!result) {
throw new IOException("Failed to show URI:" + uri);
}
}
So... is Desktop#browse supported on Linux platform just for Gnome desktop?
I am guessing this, because of that method name.
If yes, can I make a check for deadlock around my code, so I prevent this in my app? rather than checking for OS and distros?
There are already several questions on SO about that issue:
There is also this discussion:
https://bugs.launchpad.net/ubuntu/+source/openjdk-8/+bug/1574879
where someone says:
gnome_url_show is actually in libgnome-2-0 package
So, if the package is missing, Desktop.browse()
will fail. There are 2 solutions to fix that.
Install the libgnome package.
Execute xdg-open to open the URL, e.g.:
Runtime.getRuntime().exec(new String[]{"xdg-open", someurl});