【问题标题】:remove unused jars from project从项目中删除未使用的 jar
【发布时间】:2013-10-06 14:32:05
【问题描述】:


从我的 java (ant) 项目中删除未使用的 jar 的最简单方法是什么(工具?)。我们的项目变得非常庞大,我们想要进行清理。类路径中添加了几个 jar,但并非所有 jar 都用于编译/运行。有没有办法通过从命令行运行一些实用程序来识别不必要的 jar?
注意:我们不想遵循删除一个或多个 jar,然后编译/运行的繁琐过程测试是否需要这些。

【问题讨论】:

    标签: java ant jar


    【解决方案1】:

    如果有更好的解决方案,我很想听听。

    问题在于,即使 编译 不需要 jar,运行 也可能需要它。而这种“需要”可能是传递的。 EG:您使用的 jar 需要一个您不使用且仅在运行时使用的 jar。与运行时错误的本质一样,它们只会在您尝试执行代码时才会显现出来。最坏的情况是,在您投入生产之前可能不会发生这种情况。

    我所知道的最佳解决方案正是您不想做的:“删除一个或多个 jar,然后编译/运行以测试是否需要这些”。

    【讨论】:

      【解决方案2】:

      删除 -> 测试 -> 删除 -> 测试 -> 删除 -> 希望你喜欢 :)

      将项目更改为 maven 并仅选择您要使用的 jar。对我来说这是最简单的方法。

      【讨论】:

        【解决方案3】:

        正如 tieTYT 在他的回答中所指出的,许多 jar 仅在编译时才需要。 (例如 jdbc 实现 jars)

        另一种方法是编写一个 java 代理并收集所有类名。然后,您可以将这些类名映射到 jar 并查看是否不需要任何 jar。

        样本代理

        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... 用于蚂蚁

           <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>
        

        我们在 windows 中尝试的另一种方法是利用加载类时 jar 被锁定的事实。运行应用程序并尝试从运行时区域中删除。如果使用它,删除应该会失败。不确定这有多安全-我知道它在 linux 等上不起作用,可以毫无问题地删除文件。

        【讨论】:

        • 感谢您的回答,下次试试!
        【解决方案4】:

        这就是我最终所做的
        我使用 JBOSS TattleTale (http://www.jboss.org/tattletale) 在编译时识别未使用的 jar(它报告 17 个 jar 未使用)。
        然后对于该列表中的每个 jar,我对我的项目进行了字符串搜索,以查找是否在任何地方使用了 jar 的最高包级别(这是试图查看是否加载了属于该 jar 的任何类使用反射)。
        通过这种方式,我能够成功地从我的项目中消除 6 个罐子。
        由于编译时未使用的 jar 数量很少,因此这种方法很快。

        【讨论】:

        • 酷,感谢您的建议。你能举一个小例子来说明你是如何使用它的吗?
        • 可以在JBOSS之外使用Tattletale吗,比如Tomcat?
        猜你喜欢
        • 2014-08-03
        • 1970-01-01
        • 2021-08-23
        • 1970-01-01
        • 2011-03-10
        • 1970-01-01
        • 2020-07-29
        • 1970-01-01
        • 2010-10-14
        相关资源
        最近更新 更多