Login  Register

Re: Running a JOGL app from a single JAR file

Posted by sasq on Jan 15, 2015; 1:40pm
URL: https://forum.jogamp.org/Running-a-JOGL-app-from-a-single-JAR-file-tp4033846p4033865.html

gouessej wrote
Which version of JOGL does Gentoo provide? As far as I know, only Debian (thanks to Sylvestre) provides JOGL 2.2.4 right now, other distros provide only JOGL 2.0.2 and JOGL 1.1.1.

You're right. The version I installed a couple of days ago (which I thought will be the most recent), is jogl-2.0_rc8-r1

gouessej wrote
If something goes wrong, we'll be able to help you only if you use the very latest version.

OK, so I downloaded the 2.2.4, branch "origin/b22x" commit "78f641de80d1c37cd61e5300eeba369c6aa9b1a1" version from the JOGL website and put the selected JAR libs into my project's lib directory.

sasq wrote
Then, you're not creating a fat JAR, you're trying to apply the method called "Jar-in-Jar"

So that's where we misunderstood each other: when you were speaking about "fat JAR", I thought it means putting the library JARs into my app's JAR and loading them from there. Now I see that I was supposed to repack all the particular files into a directory structure into my app's JAR.

So I did, and it seems to work now.
Well, almost:
It works on Linux and MacOS X, but on Windows I get:

Starting up the application.
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: C:\Users\drott_000\Documents\gluegen-rt.dll
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.load0(Unknown Source)
        at java.lang.System.load(Unknown Source)
        at com.jogamp.common.jvm.JNILibLoaderBase.loadLibraryInternal(JNILibLoaderBase.java:596)
        at com.jogamp.common.jvm.JNILibLoaderBase.access$000(JNILibLoaderBase.java:64)
        at com.jogamp.common.jvm.JNILibLoaderBase$DefaultAction.loadLibrary(JNILibLoaderBase.java:96)
        at com.jogamp.common.jvm.JNILibLoaderBase.loadLibrary(JNILibLoaderBase.java:459)
        at com.jogamp.common.os.DynamicLibraryBundle$GlueJNILibLoader.loadLibrary(DynamicLibraryBundle.java:388)
        at com.jogamp.common.os.Platform$1.run(Platform.java:209)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.jogamp.common.os.Platform.(Platform.java:179)
        at javax.media.opengl.GLProfile.(GLProfile.java:120)
        at texQuads.Main.main(Unknown Source)

from one user, and the following from another user:

c:\> java -jar TextureQuads.jar
Starting up the application.
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: c:\\gluegen-rt.dll
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.load0(Unknown Source)
        at java.lang.System.load(Unknown Source)
        at com.jogamp.common.jvm.JNILibLoaderBase.loadLibraryInternal(JNILibLoaderBase.java:596)
        at com.jogamp.common.jvm.JNILibLoaderBase.access$000(JNILibLoaderBase.java:64)
        at com.jogamp.common.jvm.JNILibLoaderBase$DefaultAction.loadLibrary(JNILibLoaderBase.java:96)
        at com.jogamp.common.jvm.JNILibLoaderBase.loadLibrary(JNILibLoaderBase.java:459)
        at com.jogamp.common.os.DynamicLibraryBundle$GlueJNILibLoader.loadLibrary(DynamicLibraryBundle.java:388)
        at com.jogamp.common.os.Platform$1.run(Platform.java:209)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.jogamp.common.os.Platform.(Platform.java:179)
        at javax.media.opengl.GLProfile.(GLProfile.java:120)
        at texQuads.Main.main(Unknown Source)

The "Starting up the application." piece comes from my app's main function, so it seems that at least the Java libs are properly being loaded and the application runs. But there is some problem with loading the native libs on Windows (gluegen-rt.dll in particular). On other platforms (Linux and MacOS X) it runs fine.

I have the Windows native libs in my JAR, I checked. Here's how it looks like:

$ jar  tf  build/jar/TextureQuads.jar  natives
natives/
natives/linux-amd64/
natives/linux-amd64/libjogl_desktop.so
natives/linux-amd64/libjogl_mobile.so
natives/linux-amd64/libnativewindow_awt.so
natives/linux-amd64/libnativewindow_x11.so
natives/linux-amd64/libnewt.so
natives/linux-amd64/libgluegen-rt.so
natives/windows-amd64/
natives/windows-amd64/jogl_desktop.dll
natives/windows-amd64/jogl_mobile.dll
natives/windows-amd64/nativewindow_awt.dll
natives/windows-amd64/nativewindow_win32.dll
natives/windows-amd64/newt.dll
natives/windows-amd64/gluegen-rt.dll
natives/macosx-universal/
natives/macosx-universal/libjogl_desktop.jnilib
natives/macosx-universal/libjogl_mobile.jnilib
natives/macosx-universal/libnativewindow_awt.jnilib
natives/macosx-universal/libnativewindow_macosx.jnilib
natives/macosx-universal/libnewt.jnilib
natives/macosx-universal/libgluegen-rt.jnilib

so everything seems to be in place. But Windows says otherwise...

gouessej wrote
This problem is already solved in JOGL but please use the example I gave you as is first. If you complicate things now, you will never succeed in making it work.

Well, though I'm an experienced programmer in C++ and a bunch of other languages, I'm still a noob when it comes to Java. I learn how to use JOGL since a week so far, and it's still hard to me to grasp some of these things. I already wasted a couple of days trying to make it compile, and then run, by setting up all these classpaths & stuff and testing lots of different combinations. Then I wasted another couple of days trying to figure out how to make those JARs according to your directions. Although I appreciate your help, I must admit that the information you provide is very scarce and enigmatic, it is all very poorly documented (otherwise I would figure it out myself from reading the docs & wikis). I know that you have a clear picture in your head of how it all works, but I don't, and I have a hard time having to actively dig these informations out from your head, and figuring out what question should I ask next to get another important piece you forgot to tell me.

gouessej wrote
Don't get into unnecessary complications and you'll make your self-contained JAR very soon.

That's the point: I don't know which solutions are "unnecessary complications" as long as I don't have a clear picture of how it all works internally. I must do a lot of experimenting in a trial-and-error approach and waste a lot of time – a time which could be saved if you state all these little details clearly from the very beginning instead of waiting for me to dig them up from your head. I'm not clairvoyant yet.

One of these important details I missed was the fact that JOGL has its own fancy mechanism for loading these native libraries from the JAR file, and that they have to be put in special locations with hard-coded names to make it work. Not knowing that, I must have to go through several failed attempts with different combinations of these paths before it finally worked. I did read the links you provided, and I did use the <zipfileset> trick, just in a wrong way, with wrong paths.

But that was only after you enlightened me that you didn't mean putting entire JARs into my app's JAR under the "fat JAR" name, but repacking them as plain files in a particular directory structure. You could tell me that a couple of posts ago, when I first asked about putting these JARs into my app's JAR, and you would save me some random erring then.

So is it me who makes unnecessary complications? Or is it the whole jumping through hoops I experience here which actually makes it harder?