remove unused jars from project

15,324

Solution 1

This is what I did finally
I used JBOSS TattleTale (http://www.jboss.org/tattletale) to identify unused jars at compile time (It reported 17 jars as unused).
Then for each of the jar in that list, I did a string search on my project to find if the highest package level of the jar was used anywhere (this is an attempt to see if any class belonging to this jar was loaded using reflection).
This way I was able to successfully eliminate 6 jars from my project.
Since, number of unused jars at compile time was small, this approach was quick.

Solution 2

If there's a better solution to this, I'd love to hear it.

The problem is that even if a jar isn't needed to compile, it could be needed to run. And this "need" could be transitive. EG: A jar you use needs a jar you don't use and only at runtime. As is the nature of runtime errors, they'll only reveal themselves when you try to execute the code. Worst case, that may not occur until you're running in production.

The best solution I know of is exactly what you don't want to do: "removing one or more jars, then compile/run to test if those are required or not".

Solution 3

Remove -> Test -> Remove -> Test -> Remove -> Hope you enjoy :)

Change project to maven and select only jar you wanna use. For me this is the easiest way.

Solution 4

As noted by tieTYT in his answer, many jars are needed only at compile time. (for example jdbc implementation jars)

Another approach could be to write a java agent and collect all classnames. You can then map these classnames to jar and see if any jars are not needed.

Sample agent

package com;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;


public class NameAgent {


    public static void premain(String agentArgs, Instrumentation inst) {

        inst.addTransformer(new Tranformer(), true);
    }


    static class Tranformer implements ClassFileTransformer {

        @Override
        public byte[] transform(ClassLoader loader,
                                String className,
                                Class<?> classBeingRedefined,
                                ProtectionDomain protectionDomain,
                                byte[] classfileBuffer) throws IllegalClassFormatException {
            System.out.println("loading-class:" + className);
            return classfileBuffer;
        }
    }

}

Build.xml... for ant

   <project name="namedump" default="dist" basedir=".">

    <property name="src" value="src"/>
    <property name="build" value="build"/>
    <property name="dist" value="dist"/>

    <target name="init">
        <mkdir dir="${build}"/>
        <mkdir dir="${dist}"/>
    </target>

    <target name="compile" depends="init">
        <javac srcdir="${src}" destdir="${build}" optimize="true" includeantruntime="false"/>
    </target>

    <target name="dist" depends="compile">
        <jar jarfile="${dist}/namecollector.jar">
            <fileset dir="${build}"/>
                <manifest >
                    <attribute name="Premain-Class" value="com.NameAgent" />
                    <attribute name="Can-Redefine-Classes" value="true" />
                    <attribute name="Can-Retransform-Classes" value="true" />

                </manifest>
        </jar>
        <pathconvert property="absdist" dirsep="/">
            <path location="${dist}"/>
        </pathconvert>
        <echo>
            To use, add the following to the JVM command-line options.

            -javaagent:${absdist}/namecollector.jar
        </echo>
    </target>

    <target name="clean">

        <delete dir="${build}"/>
        <delete dir="${dist}"/>
    </target>
</project>

Another approach we tried in windows was using the fact that the jars get locked when classes are loaded. Run the application and try to delete from runtime area. If it was used, delete should fail. Not sure how safe this is- I know that it does not work on linux etc, the files can be deleted without problem.

Share:
15,324
flowerpot
Author by

flowerpot

Updated on July 23, 2022

Comments

  • flowerpot
    flowerpot almost 2 years


    What is the easiest way (tool ?) to remove unused jars from my java (ant ) project. Our project has become really huge, and we want to do a clean up. There are several jars that are added to the classpath, but not all are used for compile/run. Is there a way to identify the unnecessary jars by running some utility from command line?
    Note: we do not want to follow the tedious process of removing one or more jars, then compile/run to test if those are required or not.

  • flowerpot
    flowerpot over 10 years
    Thanks for your answer, will try it next time!
  • Frederick Nord
    Frederick Nord over 7 years
    cool, thanks for the suggestion. Can you give a small example of how you use it?
  • user7294900
    user7294900 over 6 years
    Can Tattletale be used outside JBOSS, with Tomcat for example?