0

I'd like to know if it is possible to insert all the libraries needed inside a single jar.

Why? I have a launcher, that launches an executable jar. This launcher, downloads at runtime the bytes containing all the code.

The problem here is that this jar that I am trying to send,is quite heavy, and most of this weight is just libraries.

A nice thing to have would be to download the libs when necessary, and download the actual code (it is just a few megabytes) always at runtime.

The structure would be something like this:

So, the question is, is there a way to pack all the jars inside a single jar?

Also, how would I access those inside my program?

Thanks.

EDIT

Here is the structure:

Jar 1: My code, this includes classes that I wrote and all the resources I might use in my code (images for example). Also I'd need to have the libs needed to load Jar 2

Jar 2: All the libraries that my code uses in it's most complex functions(Instead of having guava, openJDK, ecc. all split, I'd like them to be all together in a single jar)

What I do NOT want

A solution for a single jar containing everything. I can do that with eclipse's export function. Also, it is not what I am asking for. This means that I want the exact opposite of a "fat jar".

Obviously I'd like to know how, I could build Jar 2 and how I could access the libs in it.

Jane S.
  • 33
  • 6
  • include it into a build – logger Dec 13 '17 at 21:21
  • Yeah how do I do that? – Jane S. Dec 13 '17 at 21:22
  • 1
    @JaneS. use tools like Maven or Gradle to build the executable jar (into something called a fat jar - containing all the dependencies). You can then take this fat jar and run it. Use wrappers for both Gradle and Maven so that you don't have to have them installed on the target system (wrappers are just bootstraps which, like your launcher, download the actual code of the build tool to be executed) – mszymborski Dec 13 '17 at 21:24
  • With eclipse you can also achieve this in a manual process. – Markus Dec 13 '17 at 21:25
  • I want to do the exact opposite, actually. I'd like to split the code from the libraries (so the result would be two jars, the code one with only the basic libraries needed to load the other ones, and the full library one). – Jane S. Dec 13 '17 at 21:25
  • Could you tell us more what the launcher does? Ideally you'd have the libraries you need at maven central, or a similar repository, then declare them in the build tool's config file, which would pull them and add them to classpath. Usually the module consists of the build tool config (which declares dependencies), resources (config files for your application and such) and the code which uses these downloaded libraries. – mszymborski Dec 13 '17 at 21:28
  • @mszymborski The launcher connects to a database, downloads the bytes and packs them into a jar, and then executes the resulting jar (This is great for updating on the fly). This obviously would be much better if the code jar (That will be the only one updated frequently) detaches itself from the libraries. – Jane S. Dec 13 '17 at 21:31
  • Executable jar needs all of its depended classes packed inside it. – tsolakp Dec 13 '17 at 21:33
  • I know that. I just want to split the libraries from my code (for example I'd like to put guava and another 2 libs, in another jar) – Jane S. Dec 13 '17 at 21:36
  • @mszymborski I've edited the question. – Jane S. Dec 13 '17 at 21:43
  • @JaneS. - thanks for notifying me. Either of Maven or Gradle would do fine here, they both will take care of finding these libraries at online repos like jcenter or maven central, resolving their version, downloading them, adding them to classpath and running your application. Description on how to use them would be too general for SO though, so please refer to examples like this one: https://docs.gradle.org/current/userguide/tutorial_java_projects.html - application plugin might also prove to be helpful in your case. – mszymborski Dec 13 '17 at 21:51
  • @mszymborski is there a way to do exactly what I asked? – Jane S. Dec 13 '17 at 21:56
  • @JaneS. You can assemble that (I'm not sure about running it), but it would be kind of ugly - the usual way of assembling jar 2 and providing it to things in jar 1 is to have a project containing everything in jar 1 (unpacked), and then having contents of jar 2 dynamically downloaded by a build tool, then glued to the jar 1, again using the said build tool. Contents of jar 2 are cached, so they are not downloaded each time you run your application. If that's not what you are looking for then I'm afraid I won't be able to help you today. – mszymborski Dec 13 '17 at 22:02
  • @mszymborski Well at least you gave me some ideas. I even thought of using reflection, but that would be a huge pain in the ass to translate all the code in reflection code. Though there's got to be an easy way to do this. – Jane S. Dec 13 '17 at 22:05
  • @JaneS. If you are interested in reloading these classes when the application is running there are solutions for that, for instance OSGi - however it's kind of a pain in the ass to work with, and modern tooling support is lacking at best (except for Eclipse which is built on a plugin platform called RCP, which is built on top of OSGi) – mszymborski Dec 13 '17 at 22:09

1 Answers1

1

The artifact you want to assemble is called a "fat JAR". Build tools like Maven, Gradle or SBT provide you with a way to assemble it.

You can read more about it here.

stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
  • I think that what I am searching for is the exact opposite. I'd like to have two jars, a "slim" one, with the code and the basic libraries needed to retrieve the libs from the other jar, and the other jar, the one that contains all the libraries. – Jane S. Dec 13 '17 at 21:29
  • I've edited the post. – Jane S. Dec 13 '17 at 21:44