2013-09-30 17 views
7


Qual è il modo più semplice (strumento?) Per rimuovere i file inutilizzati dal mio progetto java (ant). Il nostro progetto è diventato davvero enorme e vogliamo fare una pulizia. Ci sono diversi vasi che vengono aggiunti al classpath, ma non tutti sono usati per la compilazione/esecuzione. C'è un modo per identificare i barattoli non necessari eseguendo qualche utilità dalla riga di comando?
Nota: non vogliamo seguire il noioso processo di rimozione di uno o più giare, quindi compilare/eseguire per verificare se sono richiesti o meno.rimuovere i jar inutilizzati dal progetto

risposta

9

Questo è quello che ho fatto finalmente
ho usato JBOSS Tattletale (http://www.jboss.org/tattletale) per identificare i vasi inutilizzati al momento della compilazione (ha segnalato 17 vasetti come non utilizzati).
Quindi per ognuno dei jar in quella lista, ho fatto una ricerca stringa sul mio progetto per scoprire se il livello di pacchetto più alto del jar fosse usato ovunque (questo è un tentativo di vedere se qualsiasi classe appartenente a questo jar è stata caricata usando la reflection).
In questo modo sono riuscito a eliminare con successo 6 jar dal mio progetto.
Poiché il numero di vasi inutilizzati in fase di compilazione era ridotto, questo approccio era rapido.

+0

tattle tale rules –

+0

cool, grazie per il suggerimento. Puoi dare un piccolo esempio di come lo si utilizza? –

+0

È possibile utilizzare Tattletale all'esterno di JBOSS, ad esempio con Tomcat? – user7294900

4

Se c'è una soluzione migliore, mi piacerebbe sentirla.

Il problema è che, anche se un barattolo non è necessario per compilare , potrebbe essere necessario per run. E questo "bisogno" potrebbe essere transitivo. Ad esempio: un vaso che usi ha bisogno di un vaso che non usi e solo in fase di esecuzione. Come è la natura degli errori di runtime, si rivelano solo quando si tenta di eseguire il codice. Il caso peggiore, che potrebbe non verificarsi fino a quando non si sta eseguendo in produzione.

La soluzione migliore che conosco è esattamente ciò che non si vuole fare: "rimuovere uno o più jar, quindi compilare/eseguire per verificare se sono richiesti o meno".

2

Rimuovi -> Test -> Rimuovi -> Test -> Rimuovi -> Spero che vi piaccia :)

Change progetto per Maven e selezionare solo vaso che si desidera utilizzare. Per me questo è il modo più semplice.

1

Come notato da tieTY nella sua risposta, molti vasi sono necessari solo in fase di compilazione. (ad esempio jdbc application jars)

Un altro approccio potrebbe essere quello di scrivere un agente java e raccogliere tutti i nomi di classe. È quindi possibile mappare questi nomi di classe in jar e vedere se non sono necessari eventuali jar.

Agente d'esempio

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 ... per formica

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

Un altro approccio che abbiamo provato in finestre stava usando il fatto che i vasi si ritrovano bloccati quando le classi vengono caricate. Esegui l'applicazione e prova a eliminare dall'area di runtime. Se è stato usato, l'eliminazione dovrebbe fallire. Non sono sicuro di quanto sia sicuro - so che non funziona su Linux ecc., I file possono essere cancellati senza problemi.

+0

Grazie per la risposta, proverò la prossima volta! – flowerpot

Problemi correlati