I am getting UnsatisfiedLinkError in a LibGdx project, when trying to run a desktop standalone version of it. Note, this problem doesn't occur if I simply run a desktop version directly without building a standalone jar for it, only if I build a desktop jar first, and then try to run that. It is interesting to note that, it was overall a lot easier to run the desktop version directly, and I wasn't even to come close to running a standalone desktop jar until I hunted down a whole bunch of jar files, and added them manually to the LibGdx project.
I am using Android Studio 3.3, with gradle 4.10, and Java 1.8.0_201 on Windows 10 x64, and have deployed a version of my LibGdx app to the desktop, using the 'gradle' command:
gradle desktop:dist
from the ProjectRoot.
And then upon running the jar file created by that, by typing into the command line from the ProjectRoot:
cd desktop/build/libs
, then java -jar desktop-1.0.jar
upon doing so I get an UnsatisfiedLinkError error
I tried copying the jar file over to Linux and tested it there too, and I got the same error.
I did some searching, and I found a suggestion that it might be that the call to new SpriteBatch()
was happening too early:
as in before the create()
function in the core module, but that wasn't the problem, because the new SpriteBatch()
call was never any earlier than that.
Also the suggestion from that link to use the LibGdx Setup Generator
didn't help me, because I already used that LibGdx Setup Generator
GUI tool to create this same project, and I'm still having this problem.
I noticed though that from the output of the program, that it was throwing that UnsatifisedLinkError exception on the new SpriteBatch()
call, as that link did make a reference to, but it was being called from the create()
function, and not earlier than that.
I did an experiment and found that if I removed the new SpriteBatch()
call altogether and all other code that depended on that call, such as creating a texture, and using the sprite batch to draw that texture. I found that by doing that, the program ran without getting the error, of course I also wasn't able to draw anything that way.
So, then I did another experiment and moved the new SpriteBatch()
call out of the create function and down into the render()
function in the following way, as you will notice in the code. I simply tried to create the SpriteBatch() every time the render() function executes, if it hasn't already been created, and output how many times it threw the UnsatisfiedLinkError exception
-------------------------MyGdxGame.java--------------------------------------
package com.mygdx.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
long numAttempts = 0;
@Override
public void create () {
}
@Override
public void render () {
if (batch == null) {
try {
batch = new SpriteBatch();
} catch (UnsatisfiedLinkError error) {
System.out.println("Failed create SpriteBatch attempt #" + numAttempts);
++numAttempts;
}
if (batch != null) {
img = new Texture("badlogic.jpg");
}
}
Gdx.gl.glClearColor(1, 1, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//batch.begin();
//batch.draw(img, img.getWidth(), 0);
//batch.end();
}
@Override
public void dispose () {
//batch.dispose();
//img.dispose();
}
}
That code above ended up creating this output:
Failed create SpriteBatch attempt #0
Failed create SpriteBatch attempt #1
Failed create SpriteBatch attempt #2
Failed create SpriteBatch attempt #3
Failed create SpriteBatch attempt #4
Failed create SpriteBatch attempt #5
Failed create SpriteBatch attempt #6
Failed create SpriteBatch attempt #7
Failed create SpriteBatch attempt #8
Failed create SpriteBatch attempt #9
Failed create SpriteBatch attempt #10
Failed create SpriteBatch attempt #11
Failed create SpriteBatch attempt #12
And it seems it would have just kept on going, saying "Failed create SpriteBatch attempt #..." if I had allowed the app to keep running.
As, you can see, it seems like no matter how many render frames have occurred, new SpriteBatch()
throws the UnsatifiedLinkError
exception, so this is clearly not a problem simply because I called new SpriteBatch()
too early in the program.
I also saw another suggestion from here that I should I do something like this for the desktop version:
static {
GdxNativesLoader.load();
}
And somewhere else, I don't remember where, I saw this suggestion:
LwjglNativesLoader.load();
so I tried both of these, not at the same time though, and neither worked, I did so by putting them in the DesktopLauncher file as so:
--------DesktopLauncher.java-------------------------------------------
package com.mygdx.game.desktop;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl.LwjglNativesLoader;
import com.badlogic.gdx.utils.GdxNativesLoader;
import com.mygdx.game.MyGdxGame;
public class DesktopLauncher {
static {
//GdxNativesLoader.load(); // I tried with this line of code
//LwjglNativesLoader.load(); // and separately with this line
}
public static void main (String[] arg) {
//GdxNativesLoader.load(); // and separately with this line, here
//LwjglNativesLoader.load(); // and separately with this line, here
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
new LwjglApplication(new MyGdxGame(), config);
}
}
None of that fixed it. I also remember seeing some links that were suggesting maybe there is a mismatch in my gdx native jars and my gdx jar, but I wasn't sure how to check that, but I will show my list of jars that I added to desktop/libs
folder and my gradle.build
file:
--------jar files:-------------
core-1.0.jar
desktop-1.0.jar
gdx-1.9.9.jar
gdx-backend-lwjgl-1.9.9.jar
gdx-backend-lwjgl-natives.jar
gdx-natives.jar
gdx-openal.jar
gdx-platform-1.9.9.jar
jinput-2.0.5.jar
jinput-platform-2.0.5-natives-linux.jar
jinput-platform-2.0.5-natives-osx.jar
jinput-platform-2.0.5-natives-windows.jar
jutils-1.0.0.jar
lwjgl-2.9.0.jar
lwjgl-2.9.2.jar
lwjgl-3.2.1.jar
lwjgl-openal-3.2.1.jar
lwjgl-platform-2.9.2-natives-linux.jar
lwjgl-platform-2.9.2-natives-osx.jar
lwjgl-platform-2.9.2-natives-windows.jar
And here is the part of my build.gradle file where I include the jar files I needed to add manually to even get a desktop standalone version of my LibGdx version to run at all:
----part of my build.gradle file-----------
project(":desktop") {
apply plugin: "java"
dependencies {
implementation project(":core")
// ... a bunch of irrelevant implementation lines here
compile files("libs/gdx-1.9.9.jar")
compile files("libs/gdx-backend-lwjgl-1.9.9.jar")
compile files("libs/lwjgl-2.9.0.jar")
compile files("libs/core-1.0.jar")
compile files("libs/desktop-1.0.jar")
compile files("libs/gdx-natives.jar")
// Noticed I commented these ones out
// compile files("libs/gdx-backend-lwjgl-natives.jar")
//compile files("libs/gdx-platform-1.9.9.jar")
//compile files("libs/lwjgl-3.2.1.jar")
compile files("libs/lwjgl-openal-3.2.1.jar")
compile files("libs/jinput-2.0.5.jar")
// Noticed I also commented out these
//compile files("libs/jinput-platform-2.0.5-natives-linux.jar")
//compile files("libs/jinput-platform-2.0.5-natives-osx.jar")
//compile files("libs/jinput-platform-2.0.5-natives-windows.jar")
//compile files("libs/jinput-1.0.0.jar")
compile files("libs/jutils-1.0.0.jar")
compile 'org.lwjgl.lwjgl:lwjgl:2.9.2'
compile files("libs/lwjgl-2.9.2.jar")
compile files("libs/lwjgl-platform-2.9.2-natives-linux.jar")
compile files("libs/lwjgl-platform-2.9.2-natives-osx.jar")
compile files("libs/lwjgl-platform-2.9.2-natives-windows.jar")
}
}
In case you're wondering, I always make sure my core-1.0.jar
and desktop-1.0.jar
are up to date, by building my desktop version, copying those jars into desktop/libs
folder, and then rebuilding that, so that's not part of the problem.
Anyway, so after all this research, and all these experiments, I have yet failed to find the cause of and solution to my problem. Any help would be much appreciated, thank you very much!
Post edit:
My classpath is this:
0: C:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar
1: C:\Program Files\Java\jdk1.8.0_201\jre\lib\deploy.jar
2: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar
3: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar
4: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar
5: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar
6: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar
7: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar
8: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar
9: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar
10: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar
11: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar
12: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar
13: C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar
14: C:\Program Files\Java\jdk1.8.0_201\jre\lib\javaws.jar
15: C:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar
16: C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar
17: C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfxswt.jar
18: C:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar
19: C:\Program Files\Java\jdk1.8.0_201\jre\lib\management-agent.jar
20: C:\Program Files\Java\jdk1.8.0_201\jre\lib\plugin.jar
21: C:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar
22: C:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar
23: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\build\classes\java\main
24: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\build\classes\kotlin\main
25: C:\Users\me\AndroidStudioProjects\TestHtml\core\build\classes\java\main
26: C:\Users\me\.gradle\caches\modules-2\files-2.1\de.tomgrill.gdxdialogs\gdx-dialogs-core\1.2.5\c55ef7e82d013ea7d99a66dcbdc24cfa7127337e\gdx-dialogs-core-1.2.5.jar
27: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.box2dlights\box2dlights\1.4\3d77ad5b4164fb32fc67e2446e35911bb0aaf0bd\box2dlights-1.4.jar
28: C:\Users\me\.gradle\caches\modules-2\files-2.1\net.dermetfan.libgdx-utils\libgdx-utils-box2d\0.13.4\918d79a20ea3c898cdb3611782c5b2bfa6ec575b\libgdx-utils-box2d-0.13.4.jar
29: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d\1.9.9\e9a43c50fbe4f1e26dd0af5d2e78d125549e7f6b\gdx-box2d-1.9.9.jar
30: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.ashley\ashley\1.7.0\a7c4083c0a42027a3c03ba7ccecef6cbe1c5f0a4\ashley-1.7.0.jar
31: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-ai\1.8.0\ec30677d8ab1a8b8aa4b853c5f4e4b1361f50bf5\gdx-ai-1.8.0.jar
32: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-controllers\1.9.9\55b69a040e076b17d01a5057f9cb2ce338a3331a\gdx-controllers-1.9.9.jar
33: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.github.czyzby\gdx-lml-vis\1.9.1.9.6\951c197ebe8c9644bd555722c449fa4cfda527fb\gdx-lml-vis-1.9.1.9.6.jar
34: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.kotcrab.vis\vis-ui\1.3.0\639741faa66a560197ee06a9412949402c831796\vis-ui-1.3.0.jar
35: C:\Users\me\.gradle\caches\modules-2\files-2.1\net.dermetfan.libgdx-utils\libgdx-utils\0.13.4\27affad2873d1c9c366a2290fc51f3927f3a5f83\libgdx-utils-0.13.4.jar
36: C:\Users\me\.gradle\caches\modules-2\files-2.1\de.tomgrill.gdxfacebook\gdx-facebook-core\1.4.1\1b5d4948b033a4b9a8f360d0fa76c49e6e17baec\gdx-facebook-core-1.4.1.jar
37: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx\1.9.9\bf26f2f816b3cfe37ac6e66615391c30714b7030\gdx-1.9.9.jar
38: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.esotericsoftware.spine\spine-libgdx\3.6.53.1\281f862762c15a8f8a79443a57526f4238b52b8e\spine-libgdx-3.6.53.1.jar
39: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.github.czyzby\gdx-lml\1.9.1.9.6\2590018dd6fc37566e3998db2cc2ecce0155c3b4\gdx-lml-1.9.1.9.6.jar
40: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.github.czyzby\gdx-kiwi\1.9.1.9.6\c00391b240ccf1212f3acd2095b6df489d4ff281\gdx-kiwi-1.9.1.9.6.jar
41: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-tools\1.9.9\55228989f0479dd4bbe487766eda15e5d512c51e\gdx-tools-1.9.9.jar
42: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-lwjgl\1.9.9\ca8911cb94c0bfeb59f99e46ca9b92440958fb0e\gdx-backend-lwjgl-1.9.9.jar
43: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl_util\2.9.2\4b9e37300a87799856e0bd15ed81663cdb6b0947\lwjgl_util-2.9.2.jar
44: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl\2.9.2\a9d80fe5935c7a9149f6584d9777cfd471f65489\lwjgl-2.9.2.jar
45: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-platform\1.9.9\7e644cfafdb436b13b24ac7993ffab17f306b64d\gdx-platform-1.9.9-natives-desktop.jar
46: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d-platform\1.9.9\72b2916f45f3f948896eda931cd597f7e698340f\gdx-box2d-platform-1.9.9-natives-desktop.jar
47: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-controllers-desktop\1.9.9\d4b8b62f077382db145e7a94a27a994b68ce6ee\gdx-controllers-desktop-1.9.9.jar
48: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-controllers-platform\1.9.9\26b8735060fdfd7dc6529cf5085fa57144a349d9\gdx-controllers-platform-1.9.9-natives-desktop.jar
49: C:\Users\me\.gradle\caches\modules-2\files-2.1\de.tomgrill.gdxfacebook\gdx-facebook-desktop\1.4.1\709e9a585082d7b875540d33ee3a4f4787ea74c3\gdx-facebook-desktop-1.4.1.jar
50: C:\Users\me\.gradle\caches\modules-2\files-2.1\de.tomgrill.gdxdialogs\gdx-dialogs-desktop\1.2.5\233048054a845d7a59d86c54e9d74f95749f74b5\gdx-dialogs-desktop-1.2.5.jar
51: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.20\b1f3cb184c4ce4139741454df2f8fca5320f822d\kotlin-stdlib-jdk8-1.3.20.jar
52: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\510c7d317f5e9e700b9cfaac5fd38bdebf0702e0\lwjgl-platform-2.9.2-natives-windows.jar
53: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d276cdf61fe2b516c7b7f4aa1b8dea91dbdc8d56\lwjgl-platform-2.9.2-natives-linux.jar
54: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d55b46b40b40249d627a83a7f7f22649709d70c3\lwjgl-platform-2.9.2-natives-osx.jar
55: C:\Users\me\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput\2.0.5\39c7796b469a600f72380316f6b1f11db6c2c7c4\jinput-2.0.5.jar
56: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-headless\1.9.9\657d1d232f274162eb8fd600a137b2221f2fc9c\gdx-backend-headless-1.9.9.jar
57: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype\1.9.9\d947872087863b654d9a0e27a8cb10a29d6fd3d6\gdx-freetype-1.9.9.jar
58: C:\Users\me\.gradle\caches\modules-2\files-2.1\com.badlogicgames.jlayer\jlayer\1.0.1-gdx\7cca83cec5c1b2f011362f4d85aabd71a73b049d\jlayer-1.0.1-gdx.jar
59: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.jcraft\jorbis\0.0.17\8872d22b293e8f5d7d56ff92be966e6dc28ebdc6\jorbis-0.0.17.jar
60: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.20\aa17d6fd473ce53061a7b2b9d2ae96f547cae93d\kotlin-stdlib-jdk7-1.3.20.jar
61: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.20\eb2a232734e09fcd1b958a5c7520a93c6de38b32\kotlin-stdlib-1.3.20.jar
62: C:\Users\me\.gradle\caches\modules-2\files-2.1\net.java.jutils\jutils\1.0.0\e12fe1fda814bd348c1579329c86943d2cd3c6a6\jutils-1.0.0.jar
63: C:\Users\me\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\7ff832a6eb9ab6a767f1ade2b548092d0fa64795\jinput-platform-2.0.5-natives-linux.jar
64: C:\Users\me\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\385ee093e01f587f30ee1c8a2ee7d408fd732e16\jinput-platform-2.0.5-natives-windows.jar
65: C:\Users\me\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\53f9c919f34d2ca9de8c51fc4e1e8282029a9232\jinput-platform-2.0.5-natives-osx.jar
66: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.20\7d7934e26ce34da1a0a8d00e38038d7cf3375e89\kotlin-stdlib-common-1.3.20.jar
67: C:\Users\me\.gradle\caches\modules-2\files-2.1\org.jetbrains\annotations\13.0\919f0dfe192fb4e063e7dacadee7f8bb9a2672a9\annotations-13.0.jar
68: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\libs\core-1.0.jar
69: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\libs\gdx-natives.jar
70: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\libs\lwjgl-3.2.1.jar
71: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\libs\lwjgl-natives-linux.jar
72: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\libs\lwjgl-natives-macos.jar
73: C:\Users\me\AndroidStudioProjects\TestHtml\desktop\libs\lwjgl-natives-windows.jar
74: C:\Program Files\Android\Android Studio\lib\idea_rt.jar
Update:
My full desktop module in build.gradle:
project(":desktop") {
//apply plugin: "application"
//mainClassName = "DesktopLauncher"
apply plugin: "java"
dependencies {
implementation project(":core")
implementation "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
implementation "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop"
implementation "com.badlogicgames.gdx:gdx-tools:$gdxVersion"
implementation "com.badlogicgames.gdx:gdx-controllers-desktop:$gdxVersion"
implementation "com.badlogicgames.gdx:gdx-controllers-platform:$gdxVersion:natives-desktop"
implementation "de.tomgrill.gdxfacebook:gdx-facebook-desktop:1.4.1"
implementation "de.tomgrill.gdxdialogs:gdx-dialogs-desktop:1.2.5"
//implementation "com.badlogicgames.gdx:gdx:1.9.9"
compile files("libs/gdx-1.9.9.jar")
compile files("libs/gdx-backend-lwjgl-1.9.9.jar")
//compile files("libs/lwjgl-2.9.0.jar")
compile files("libs/core-1.0.jar")
//compile files("libs/desktop-1.0.jar")
compile files("libs/gdx-natives.jar")
// compile files("libs/gdx-backend-lwjgl-natives.jar")
//compile files("libs/gdx-platform-1.9.9.jar")
//compile files("libs/lwjgl-3.2.1.jar")
/*
compile files("libs/lwjgl-openal-3.2.1.jar")
compile files("libs/jinput-2.0.5.jar")
compile files("libs/jinput-platform-2.0.5-natives-linux.jar")
compile files("libs/jinput-platform-2.0.5-natives-osx.jar")
compile files("libs/jinput-platform-2.0.5-natives-windows.jar")
*/
//compile files("libs/jinput-1.0.0.jar")
compile files("libs/jutils-1.0.0.jar")
compile 'org.lwjgl.lwjgl:lwjgl:2.9.2'
compile files("libs/lwjgl-3.2.1.jar")
compile files("libs/lwjgl-platform-2.9.2-natives-linux.jar")
compile files("libs/lwjgl-platform-2.9.2-natives-osx.jar")
compile files("libs/lwjgl-platform-2.9.2-natives-windows.jar")
compile files("libs/lwjgl-natives-linux.jar")
compile files("libs/lwjgl-natives-macos.jar")
compile files("libs/lwjgl-natives-windows.jar")
}
}
GdxNativesLoader.load();
in a static block isn't working, makes me believe the problem is definitely with your classpath. Not with any code. – Dylan