自己动手精简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,也可以瘦身不少

 

 

精简jre步骤 1. 拷贝一个完整版的jre文件夹到D盘 2. 删除jre目录下所有出bin和lib目录的所有文件或目录 3. 打开cmd窗口,设置path路径为空,转到D:\jre\bin目录,运行java –version。正常显示当前Java的版本。 4. 在bin目录中新建一个temp目录,将除java.exe和java.dll外的移到temp目录中 5. 再次运行java –version命令,提示没找到verify.dll。将temp目录中的verify.dll移到bin目录中 6. 再次运行 java –version命令,提示:Could not create the Java virtual machine.错误 7. 根据测试:还要将hpi.dll和zip.dll放到bin目录中 8. 再次运行java –version命令,OK,又出现了版本信息。此时,可以将temp目录移出bin目录中。(放到桌面先) 9. 删除client目录中的除jvm.dll外的文件。转到jre目录,查看bin目录的大小,为2.89MB。但此时lib目录仍有60M有余 10. 转到lib目录,新建一个temp目录,将i386除外的目录都移动到temp目录中,再次运行java –version命令,OK 11. 再新建一个temp2目录,将charsets.jar和rt.jar外的所有文件移动到temp2目录中,再次运行 Java –version命令,OK 12. 将temp2和temp目录移到桌面。此时lib仍有48.7M接近50M。(还得努力) 13. 缩减charsets.jar和rt.jar(使用7z工具可以查看和修改jar文件的内容『直接添加和删除』)。准备做个软件来实现。 14. 缩减原则。运行java -verbose:class -version > temp.java 命令,此时在bin目录下生成了一个temp.java文件,用EditPlus打开,看到没有,要加载的就是那些类了,把不需要的全部删除就是了。 15. 原来charsets.jar没有加载呀。直接删除,再次运行java –version命令,OK 16. 接下来的工作就是裁剪rt.jar了。慢慢来。也可以做个软件来完成。可以下载一个GreenJVMMake.jar来完成。不过有时候好像有些类没加载到。要考虑更新了。 17. 裁剪玩rt.jar后,再次运行java –version ,出现了版本信息。OK 18. 转到D盘查看一下精简jre才4.47MB。不到5M。OK 19. 最小的jre制作完毕。 附带制作过程图片,可用Picasa来查看,播放模式效果更佳。 Thoams 2010-6-25 15:53
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值