Java Maven project minify the build - java

I am working on a multi module Maven project. We have created a project which builds an uber jar. The unpacked jar is about 60mb which is a problem for our client.
Are there any tools we can use to remove unused .class files within the dependencies when the build is completed?
Another option would be if we could analyse what .class files are loaded when running and produce a list of these and thus remove others from the build manually.
cheers,

I'm not sure if it could remove classes as such, but proguard has some awesome results in terms of minifying class sizes. You can see from the link it reduces the Ant module by 90%

Related

Java Maven multi modules + proguard obfuscation

I am in the process of transferring a java netbeans project that has proguard obfuscation, from ant to maven multi module. I am a newbie in maven, and after reading and trying many solutions & architectures for a few days now, I am still quite lost.
From what I have seen, there are to ways to structure my project:
option 1: option 2:
module top module top
module A module A
module B module B
module C module C
module assembly
The modules have inner dependencies between them.
'module top' is a module that has very little code, and it acts as a wrapper.
In option 1, the pom.xml for packaging the project is in 'module top'.
In option 2, 'module assembly' has no logic, just the pom.xml for packaging the project.
My goal is to package the project in one fat jar where the inner modules will be obfuscated using proguard plugin.
What I have tried so far:
I managed to obfuscate one module, but because the modules are dependent on each other, I need to keep the entire interface structure, otherwise the modules don't fit when wrapped together.
I have created a fat jar file of the entire project and used proguard to obfuscate it. Since it is a big file, around 20M, the process took a lot of time, around 15 minutes. The output file was small, about 4M, and it didn't work.
Right now I am trying to assemble all my code during the build to a distribution jar, and separate it from the library jars. my aim is to obfuscate only my modules, and add the libraries later (this is what I have seen is working for me in the ant project that I currently have).
So far all my attempts have not yielded a process that works. I can't attach the pom files because I am keep changing them when trying new stuff.
So to sum this up, these are the options as I see them:
Build & obfuscate each module separately, combine them in the top module while dealing with keeping the interfaces.
Assemble & obfuscate all my modules together, separate from the libraries.
Build a huge fat file, and obfuscate it as a whole.
Do the packaging inside 'module top' or using a dedicated 'module assembly'
What do you recommend? Any help would be appreciated
EDIT
I got a small breakthrough. using option2 and proguard GUI, I finally managed to create a working obfuscated jar. For first step I run maven-dependency-plugin with copy-dependencies to a lib folder.
Then in the proguard GUI I 'injar' all my modules, and 'libraryjar' all the rest, and created dist-obsfucated.jar
My current ModuleAssemble structure is like this:
project
target
dist-obsfucated.jar
lib
moduleA.jar
moduleB.jar
moduleC.jar
other_file1.jar
other_file2.jar
How do I assemble all the jars to an executable jar? I need tell the assembly plugin to ignore the unobsfucated modules A through C in the lib folder
EDIT #2
I managed to solve it using 'maven-antrun-plugin'

package all external classes in my jar, with Eclipse

I am working on a Hadoop project in Eclipse that depends on another one of my projects; I've included the other project in my build path, but when I export the dependent project, it only contains the classes from that same project.
Ordinarily, this would not be a problem, as I could just link the other project with the -cp flag, but Hadoop requires you to pass the jar as an argument, meaning that all of my dependencies must be inside that jar.
Is there a way, in Eclipse, to automatically build and include classes from projects that you depend on?
Thanks.
You coud use Ant to automatically build, test and export. It needs some time learning it, but its worth.
There are possible tasks (fileset, zipgroupfileset, copy) to include files, jars (unzipped) or anything into the final jar. By this way you definitly know whats inside your distribution jar and you don't need an eclipe installation running.
I suggest you take a look at maven as a build tool. You define the dependencies and build steps for each of your projects in files called pom files. The maven plugins for Eclipse (the m2e plugins) can take the configuration in the pom file and setup your Eclipse build paths and project description so that you can access the classes in your other project in Eclipse. Maven can also create a jar for you that has the classes from both projects (a "jar-with-dependencies").
In maven terms, your two projects are called "artifacts" with one having a dependency on the other.
The one downside to maven (and the cause for many negative comments about maven) is an initially steep learning curve that can be frustrating. What you're trying to do, however, is very straightforward and I expect you can find a number of examples showing you exactly what you want to do.
The first step, and that's what my answer is about, is to take a look at maven. It may seem overly complex, but it can scale to handle just about any build configuration you need as your hadoop apps get more and more complex.
You can export a project as a Runnable jar, which can be useful if you want a single jar, with dependencies included.
Select the Project. File > Export. Select the Java section. Select Runnable JAR file.
See related answer:
Eclipse: How to build an executable jar with external jar?

Setting up a maven project for already made jars

I have some jar files that I need to include in my build - I'd rather not specify them as system dependencies - that creates a nightmare for setup. I have been uploading them to artifactory and then they can be pulled down directly, but I won't always have access to artifactory while building.
What I was thinking of doing is creating a project that has these jar files in them. It could be one per or all of them (open to suggestion). I was wondering if there is a graceful way to handle this?
What I have done (which is clearly a hack) have a project that takes the jar and during the compile phase it unpacks the jar into the target/classes directory. It then packs those class files back during the package phase. it essentially creates the same jar file again...massively hackey. Could I add the jar into the resource area or is there a different project type I could use? I am open to any ideas.
You may try to use install:install-file. I would go about it in the following way.
Create project that contains all your jars in some location
Configure install:install-file in pom of this project to install jars in repository in some early phase.
Make sure that this pom is executed before anything else that depend on it. List it as first module.

Avoiding duplicate library .jars when exporting a single .jar in Eclipse

I'm using the Eclipse "Export... Runnable jar file" feature to package up my Clojure+Java application for deployment.
This works great, magically including various resources and Clojure source files etc.
The one issue I have is that various libraries I have get included multiple times from the "lib" directory dependant projects, e.g. I get four versions of the Clojure jar file due to other projects on the build path that also use Clojure.
This issue is needlessly tripling the size of my .jar file!
Is there any way to easily eliminate these duplicates other than manually deleting from the generated jar?
If there is a natural dependency graph to your projects, I would change your eclipse project settings such that only one project has the jar on the build path and it exports (by export I mean from the "Order and Export" tab in the Configure Build Path dialog) that jar for other projects to see. The other projects then have that "core" project on the build path. I believe this should naturally take care of your problem.
Edit
One comment I have is that having a jar within a jar is rarely a good idea. I would either reconsider packaging it all into a single jar (unless the point of the main file of the jar is to extract its own contents into a folder) or maybe explore the possibility of using the "Extract required libraries into generated JAR" option.

Deploying Java Files

What are the best practices (and enabling tools) to deploy Java standalone applications along with any required jar dependencies, config files, and launch scripts?
Are there any Maven plugins that easies publishing binary releases, so that users don't need to use maven for example?
Are there any Maven plugins that easies publishing binary releases, so that users don't need to use maven for example?
Use the Maven Assembly Plugin to create a binary distribution as zip/tar.gz/tar.bz2 of your project. This plugin is extremely flexible - at the price of some complexity - and you can do almost anything you want. Then deploy (in the maven sense) the produced artifact, upload it somewhere, etc.
As for dependency, I just use maven dependency copy plugin and copy all dependencies into a ./lib folder, and supply a launch script that uses the class path wildcard (that way you can change your dependencies as much as you want and don't have to change the launch script). As for configuration files, I put it in a ./config folder and again include it in my app's classpath in the launch script (The former admittedly only works for > java 1.6).
So in the end almost all my app has the following structure:
mystuff.jar launch.sh
./lib
./config
Then I'll just zip up the whole thing and give it to my users. The whole process is probably easy to automate using maven, but I confess that I do it by hand :p
If you prefer and the licenses permit, you could also just bundle all dependencies into a single jar (with expanded dependencies inside) using the assembly plugin. This tends to make the jar bulky and giving the users an updated app. more difficult. Also I had issues with it several time because of class files getting overwritten or something so I personally stick to the ./lib folder.
There's launch4j, which, if you can get it to work, will bundle up a Java app into an executable for your platform.
If your deployment target supports RPM files, I strongly suggest you investigate the rpm-maven-plugin. It allows you to easily map your project artifacts , including dependencies, to a RPM package.
I've been using it with great success to medium-scale application deployment.
You can use Oracle's ant or maven scripts:
http://docs.oracle.com/javafx/2/deployment/jfxpub-deployment.htm
The above will not only compile your code and create jar files, but it will also create binary executable (windows exe file or Mac app file). It can also create native installers. In addition it lets you include JVM with your distribution so the end use doesn't need to install Java.
Take a look at the Appassembler Maven Plugin. You may also want to combine it with the Assembly Maven Plugin.
Use the appassembler plugin to generate a set of "programs" by specifying executable names and main classes. You can also have it prepend and create an etc directory in which you can add configuration files.
If generating the directory with the start-up scripts and directory of binary files isn't enough, you can use the assembly plugin to copy over additional files (say your configuration files) into the appropriate directory and/or package your application into an archive.

Categories

Resources