欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自己动手精简jre

程序员文章站 2022-05-21 08:00:03
...

背景:

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,也可以瘦身不少

 

 

相关标签: 精简 jre