自己写的小工具---JarCleaner

本文介绍了一款名为JarCleaner的小工具,该工具能够帮助开发者识别并删除Java项目中未使用的JAR文件,有效减少lib目录的体积,提高项目的整洁度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java的jar是一个很不错的技术。可是现在开源的发展,使得一个项目中会用到很多很多的jar文件(我们的一个项目中,刚开始lib目录下有超过100兆的jar文件),一直怀疑有些文件是用不到的,但是又不太确定哪些是有用的,哪些是没用的。

想了想,决定还是做个小工具,一劳永逸地解决这个问题吧。

此小工具能完成如下功能:

1、将原来lib路径的所有jar备份到lib/bak目录下;

2、删除不用的jar

那怎么判断哪些是没用的呢?

这里用到了java -verbose:class,这个命令会将所有加载class的过程打印出来,如果是jar中的class, 还会指明是从哪个jar中加载的。

因此,通过在tomcat或者其他应用服务器的启动脚本中,添加-verbose:class,然后运行,即可获得加载信息。将其复制到一个log文件中,作为参数传递给JarCleaner即可。

  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.FileReader;
  7. import java.io.IOException;
  8. import java.io.InputStream;
  9. import java.util.HashSet;
  10. import java.util.Set;
  11. /**
  12.  * 
  13.  * JarCleaner is an utility class to remove all un-referenced jar under the webapp/lib path.<br/>
  14.  * Before run this class, you need have two informations prepared. <br/>
  15.  * 1. The webapp lib path, such as: c:/tomcat/webapps/demo/WEB-INF/lib <br/>
  16.  * 2. The log file, which is generated by console, when adding "-verbose:class" argument <br/>
  17.  * in the end of the java command which is used to start the server. 
  18.  * 
  19.  * 
  20.  * @author Leo Liu
  21.  * <a href="http://www.smilingleo.cn">Homepage</a>
  22.  *
  23.  */
  24. public class JarCleaner {
  25.     
  26.     public Set<String> getNecessaryJarSet(String appLibPath , String logFile){
  27.         
  28.         String pattern = "//[Loaded.*[///].*//.jar//]";     
  29.         Set<String> jarSet = new HashSet<String>();
  30.         
  31.         BufferedReader br = null;
  32.         try {
  33.             br = new BufferedReader(new FileReader(new File(logFile)));
  34.         } catch (FileNotFoundException ee) {
  35.             System.out.println("Can't find the log file." + ee.getMessage());
  36.         }
  37.         
  38.         String aLine = "";
  39.         while(true){
  40.             
  41.             try {
  42.                 aLine = br.readLine();
  43.             } catch (IOException e) {
  44.                 System.out.println("End of log file.");
  45.             }
  46.             
  47.             if (aLine == nullbreak;
  48.             
  49.             if (aLine.matches(pattern)){
  50.                 String[] strs = aLine.split("from");
  51.                 if (strs.length <= 0continue;
  52.                 String jarName = strs[strs.length - 1].trim();
  53.                 if (jarName.startsWith("file")){
  54.                     jarName = jarName.substring(6);
  55.                 }
  56.                 jarName = jarName.substring(0, jarName.length() - 1);
  57.                 if (jarName.indexOf("/") > 0){                  
  58.                     jarName = jarName.replaceAll("[/]""////");
  59.                 }
  60.                 // Only filter the jars in the web app path.
  61.                 if (jarName.startsWith(appLibPath)){                    
  62.                     if (!jarSet.contains(jarName))
  63.                         jarSet.add(jarName);                
  64.                 }
  65.             }
  66.         }
  67.         return jarSet;
  68.     }
  69.     public Set<String> backupOriginalJars(String appLibPath){
  70.         File libPath = new File(appLibPath);
  71.         File[] jars = libPath.listFiles();
  72.         Set<String> jarSet = new HashSet<String>();
  73.         File bakPath = new File(appLibPath + "//bak");
  74.         if (!bakPath.exists())
  75.             bakPath.mkdir();
  76.         
  77.         for (File jar : jars){
  78.             String jarName = jar.getAbsolutePath();
  79.             jarName.replaceAll("[/]""////");
  80.             jarSet.add(jarName);
  81.             // Backup the file to bak path
  82.             File newJar = new File(appLibPath + "//bak//" + jar.getName());
  83.             copyFile(newJar, jar);
  84.         }
  85.         
  86.         return jarSet;
  87.     }
  88.     
  89.     public void cleanJars(Set<String> allJars, Set<String> jarSet){
  90.         allJars.removeAll(jarSet);
  91.         
  92.         for (String jarName : allJars){
  93.             File oldJar = new File(jarName);
  94.             oldJar.delete();
  95.         }
  96.         
  97.     }
  98.     
  99.     private void copyFile(File targetFile, File file) {
  100.         if (targetFile.exists()) {
  101.             System.out.println("File:" + targetFile.getAbsolutePath()
  102.                     + " already existed, skip that file!");
  103.             return;
  104.         } else {
  105.             createFile(targetFile, true);
  106.         }
  107.         System.out.println("copied " + file.getAbsolutePath() + " to "
  108.                 + targetFile.getAbsolutePath());
  109.         try {
  110.             InputStream is = new FileInputStream(file);
  111.             FileOutputStream fos = new FileOutputStream(targetFile);
  112.             byte[] buffer = new byte[1024];
  113.             while (is.read(buffer) != -1) {
  114.                 fos.write(buffer);
  115.             }
  116.             is.close();
  117.             fos.close();
  118.         } catch (FileNotFoundException e) {
  119.             e.printStackTrace();
  120.         } catch (IOException e) {
  121.             e.printStackTrace();
  122.         }
  123.     }
  124.     private void createFile(File file, boolean isFile) {
  125.         if (!file.exists()) {
  126.             if (!file.getParentFile().exists()) {
  127.                 createFile(file.getParentFile(), false);
  128.             } else {
  129.                 if (isFile) {
  130.                     try {
  131.                         file.createNewFile();
  132.                     } catch (IOException e) {
  133.                         e.printStackTrace();
  134.                     }
  135.                 } else {
  136.                     file.mkdir();
  137.                 }
  138.             }
  139.         }
  140.     }
  141.     
  142.     
  143.     /**
  144.      * @param args
  145.      */
  146.     public static void main(String[] args) throws Exception{
  147.         if (args.length != 2){
  148.             System.out.println("Usage : java JarCleaner <webapp lib path> <class verbose log file>/n" +
  149.                     "This command will backup all jar files in your specified webapp lib path,/n" +
  150.                     "and remain the necessary jars only./n" + 
  151.                     "  <webapp lib path>    : the full path of your web application located./n" +
  152.                     "  <class verbose file> : the full path of your log file. /n" +
  153.                     "                         use:java -verbose:class to get the log content./n/n" + 
  154.                     "Note: You must shut down the server before run this command.");
  155.             System.exit(-1);
  156.         }
  157.         String appLibPath = args[0].trim();
  158.         String logFile = args[1].trim();
  159.         
  160.         JarCleaner cleaner = new JarCleaner();
  161.         // Get the referenced jars.
  162.         Set<String> jarSet = cleaner.getNecessaryJarSet(appLibPath, logFile);
  163.         
  164.         // Get all jars in web app lib path.
  165.         Set<String> allJars = cleaner.backupOriginalJars(appLibPath);
  166.         
  167.         // Remove all non-referenced jar files.
  168.         cleaner.cleanJars(allJars, jarSet);
  169.     }
  170. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值