自己动手精简jre

背景:

java程序发布时需要考虑用户的运行环境是否自带了jre,如果没有则需要将jre打包发布,然而jre目录越来越大,jre7已经上百兆,这样就大大增加了程序的大小。但是jre目录中有很多文件可能是我们程序运行时不需要的,可以删除这部分文件减小程序发布的大小,  但是怎么去删除这些运行时不需要的文件呢?

思路:

删除jre中的一个文件,再执行程序,如果程序运行正常,则证明该文件可以删除,如果程序出错则恢复删除的文件。有了这个方法,我们再在这个方法上套个for循环遍历jre目录中的文件,就可以删除jre中程序运行时不需要的文件了。

实现:

	/**
	 * 清理jre路径中不需要的文件<br>
	 * <b>@author </b>Peacenik 2013-12-28<br>
	 * @param jrePath jre路径
	 */
	public static void cleanJre(String jrePath) throws IOException
	{
		Files.walkFileTree(Paths.get(jrePath), new JreFileVisitor());
		deleteEmptyFolder(jrePath);
	}
	/**
	 * jre文件访问器<br>
	 * <b>项目名称 </b>test7<br>
	 * <b>@author </b>Peacenik 2013-12-28<br>
	 */
	private static final class JreFileVisitor extends SimpleFileVisitor<Path>
	{
		/**
		 * 计数器
		 */
		private int i = 0;

		/*
		 * <b>重写方法</b><br>
		 * @see java.nio.file.SimpleFileVisitor#visitFile(java.lang.Object, java.nio.file.attribute.BasicFileAttributes)
		 */
		@Override
		public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
		{
			FileVisitResult result = super.visitFile(file, attrs);
			tryDelete(file);
			return result;
		}

		/**
		 * 更具程序执行结果判断该文件是否可删除<br>
		 * 如果可删除,则 删除文件并返回true<br>
		 * 如果不能删除,则返回false
		 * <b>@author </b>Peacenik 2013-12-28<br>
		 * @param file 文件
		 * @return boolean
		 * @throws IOException
		 */
		private boolean tryDelete(Path file) throws IOException
		{
			String path = file.toFile().getPath();
			Path targetPath = Paths.get(path.replaceFirst("jre", "jre_back"));

			// 移除文件
			if (!Files.exists(targetPath.getParent()))
			{
				Files.createDirectories(targetPath.getParent());
			}

			if (Files.exists(targetPath))
			{
				Files.delete(targetPath);
			}

			Files.move(file, targetPath);

			boolean success = executeSuccess();
			if (!executeSuccess())
			{
				// 执行失败时恢复移除的文件
				Files.move(targetPath, file);
			}
			System.out.println((++this.i) + "\t/\t" + success + "\t/\t" + file.toFile().getPath());
			return success;
		}
	}
       /**
	 * 删除空目录<br>
	 * <b>@author </b>Peacenik 2013-12-28<br>
	 * @param folder 文件夹路径
	 */
	private static void deleteEmptyFolder(String folder) throws IOException
	{
		Files.walkFileTree(Paths.get(folder), new SimpleFileVisitor<Path>()
		{
			@Override
			public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException
			{
				FileVisitResult result = super.postVisitDirectory(dir, exc);
				if (dir.toFile().list().length == 0)
				{
					Files.delete(dir);
				}
				return result;
			}
		});
	}
        /**
	 * 执行程序,返回程序是否执行成功<br>
	 * 这个方法需要根据自己的情况进行修改
	 * <b>@author </b>Peacenik 2013-12-28<br>
	 * @return boolean
	 */
	public static boolean executeSuccess()
	{
		Process process = null;
		try
		{
			// 创建执行程序
			String[] commands = new String[] { "D:/tools/exe4j/demo/mytools/test7.exe" };
			File directory = new File("D:/tools/exe4j/demo/mytools/");
			process = Runtime.getRuntime().exec(commands, new String[] {}, directory);
			process.waitFor();

			byte[] bs = new byte[10];

			// 读取错误信息
			try (InputStream ins = process.getErrorStream())
			{
				int length = ins.read(bs);
				if (length > 0)
				{
					return false;
				}
			}

			// 读取非错误信息
			try (InputStream ins = process.getInputStream())
			{
				int length = process.getInputStream().read(bs);
				if (length != 2)
				{
					return false;
				}
			}

			// 判断返回值
			int ret = process.exitValue();
			process.destroy();
			return (ret == 0) && "ok".equals(new String(bs, 0, 2));
		}
		catch (Exception e)
		{
			return false;
		}
		finally
		{
			if (process != null)
			{
				process.destroy();
			}
		}
	}

补充:

rt.jar 这个jar文件有几十兆,可以视情况删除其中的部分package,也可以瘦身不少

猜你喜欢

转载自peacenik.iteye.com/blog/1996838