Loading libraries from an executable JAR is seriously hard.

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Loading libraries from an executable JAR is seriously hard.

bkuker
I am trying to use JOGL (2.0 rc5) in a standalone Java app run from an executable JAR.

The app's jar is packaged by re-zipping all of the libraries into one fat jar. It's not my app, I can't change that.

The JogAmp projects do seem to know how to pull a native library out of a JAR (I assume they write it to a temp directory), but the way they find that resource seems really complex... It looks for the JAR that GlueGen came in, then looks for a jar in the same directory, using a naming convention including the architecture, and then gets native libraries from that jar.

This makes it really tough to package it into a single far jar. The eclipse jars-in-a-jar method works, but the "fat jar" method does not.

Is there any way I can just put the natives in my Jar, and give them to GlueGen & JOGL as streams (getResourceFromStream) or some such?
Reply | Threaded
Open this post in threaded view
|

Re: Loading libraries from an executable JAR is seriously hard.

Sven Gothel
Administrator
On 04/04/2012 11:46 PM, bkuker [via jogamp] wrote:

>
>
> I am trying to use JOGL (2.0 rc5) in a standalone Java app run from an
> executable JAR.
>
> The app's jar is packaged by re-zipping all of the libraries into one fat
> jar. It's not my app, I can't change that.
>
> The JogAmp projects do seem to know how to pull a native library out of a
> JAR (I assume they write it to a temp directory), but the way they find that
> resource seems really complex... It looks for the JAR that GlueGen came in,
> then looks for a jar in the same directory, using a naming convention
> including the architecture, and then gets native libraries from that jar.
>
> This makes it really tough to package it into a single far jar. The eclipse
> jars-in-a-jar method works, but the "fat jar" method does not.
>
Very good assessment & description, thank you.

> Is there any way I can just put the natives in my Jar, and give them to
> GlueGen & JOGL as streams (getResourceFromStream) or some such?

Not as it is today, but we may add something to serve such a need.

Currently the only way to determine the right JAR file for each platform
is the JAR file name - as you pointed out correctly.

The native plain library files itself don't have a unique name.

The current schema, one native JAR file per platform very well
serves the traditional Applet/Webstart deployment since it saves
bandwidth and it also serves most stand alone application.

Having a fat JAR would at least require the native libraries to reside
in a subfolder using our naming convention.
Such implementation would be doable with minor changes to the current code.

However, I don't see a conflict w/ Jar in Jar, which I personally would favor
here. It also gives one the opportunity to use
the original [signed] JAR files, so you can maintain the files
origin and identity.

Well, using a fat JAR here implies that in the JOGL layer,
the fat JAR content is already 'known' and available to the classloader.
Hence we can skip extracting files, but 'just' need to find the platform's
subfolder and continue there (copy files to temp folder and allow them to
loaded by the classloader).
We may even be able to skip the copy part, if it is ensured that only one
ClassLoader will access those libraries (no Applets .. ).

Anybody out there who cannot live with the current use case,
restricted to native Jar files per platform incl. Jar-In-Jar ?

For sure this won't be done for RC6.
Please add a bugreport (enhancement) with the content of your and my writings
and we can vote/discuss it further.

Thank you.

Cheers, Sven


signature.asc (910 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Loading libraries from an executable JAR is seriously hard.

bkuker
It sounds from some other posts like you are planing to drop the architecture specific jars in favor of one all-encompassing JAR. If that is the case I would assume you are going to have to use architecture specific directories anyway?

[arch]/[libname].[so,dll,whatever]

Currently it looks like the code goes:

1. Try to load library from natives jar in same location as gluegen jar.
2. Try to load library from library.path

could it be as simple as:

1. Try to load library from natives jar in same location as gluegen jar.
2. Try to load library from SomeJogAmpClass.class.getClassLoader().getResource([arch]/[library]).
3. Try to load library from library.path

I assume once you have an input stream for the library you can copy it to whatever temp place it goes to and loadLibrary(). Resources are commonly used, easy to understand, and in a pinch if someone needed to do something crazy in a standalone app they could do it with a custom classloader.
Reply | Threaded
Open this post in threaded view
|

Re: Loading libraries from an executable JAR is seriously hard.

Sven Gothel
Administrator
On 04/05/2012 11:53 AM, bkuker [via jogamp] wrote:
>
>
> It sounds from some other posts like you are planing to drop the architecture
> specific jars in favor of one all-encompassing JAR.

I never said that - nope. I especially emphasized that the platform specific
native JARs are very efficient when it comes to networking (Applets ..).

However, I am open to give the fat-jar method a thought as a fall-back.

> If that is the case I

[as a fall-back]

> would assume you are going to have to use architecture specific directories
> anyway?
>
> [arch]/[libname].[so,dll,whatever]

as I mentioned .. yes

>
> Currently it looks like the code goes:
>
> 1. Try to load library from natives jar in same location as gluegen jar.
> 2. Try to load library from library.path
>
> could it be as simple as:
>
> 1. Try to load library from natives jar in same location as gluegen jar.
> 2. Try to load library from
> SomeJogAmpClass.class.getClassLoader().getResource([arch]/[library]).
> 3. Try to load library from library.path
>
> I assume once you have an input stream for the library you can copy it to
> whatever temp place it goes to and loadLibrary(). Resources are commonly
> used, easy to understand, and in a pinch if someone needed to do something
> crazy in a standalone app they could do it with a custom classloader.
>
A custom ClassLoader has it's own restrictions here,
hence I chose to use specific GlueGen methods to utilize this functionality.
For example in an IDE or Applet environment we cannot guarantee an entry point
where a user switches to a new ClassLoader, we provide. Note that native
libraries, static data and classes are only valid from the loading ClassLoader.

We have somehow solved this problem in Android, but it's quite tricky
and we don't want to force people to deal with such problems.

However, the fat JAR can be achieved with the current API model, yes.

~Sven



signature.asc (910 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Loading libraries from an executable JAR is seriously hard.

bkuker
Thank you, I must have misunderstood:

> I guess it's time to remove the per platform archive files
> in favor of the all-platform one.

> Will keep the native libraries in there,
> however we may remove it's reference from the wiki (howto, guides, etc)
> or at least mark them as *alternative*. They cost lots of confusions.

From another thread.

I'll keep trying to find a way forward with the fat jar, before trying to convince the upstream project to switch to jar-in-jar, but the takeaway for now is that JOGL prefers a jar-in-jar as the solution for a single file executable jar.

> However, the fat JAR can be achieved with the current API model, yes.

Do you mean this with or without changes to the JogAmp libraries themselves?
Reply | Threaded
Open this post in threaded view
|

Re: Loading libraries from an executable JAR is seriously hard.

Sven Gothel
Administrator
On 04/05/2012 01:41 PM, bkuker [via jogamp] wrote:

>
>
> Thank you, I must have misunderstood:
>
>> I guess it's time to remove the per platform archive files
>> in favor of the all-platform one.
>
>> Will keep the native libraries in there,
>> however we may remove it's reference from the wiki (howto, guides, etc)
>> or at least mark them as *alternative*. They cost lots of confusions.
>
>>From another thread.
That was regarding the platform 7z archive file, not JAR files.

>
> I'll keep trying to find a way forward with the fat jar, before trying to
> convince the upstream project to switch to jar-in-jar, but the takeaway for
> now is that JOGL prefers a jar-in-jar as the solution for a single file
> executable jar.
>
>> However, the fat JAR can be achieved with the current API model, yes.
>
> Do you mean this with or without changes to the JogAmp libraries themselves?

Yes, we need to make changes in GlueGen to support that.
I merely mentioned that we don't need to change the API
or anything to achieve that feature.

Please put all these emails in a bugreport (our bugzilla), thank you.

~Sven


signature.asc (910 bytes) Download Attachment