﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-java_one</title><link>http://www.blogjava.net/nan306635934/</link><description>java_one</description><language>zh-cn</language><lastBuildDate>Sun, 12 Apr 2026 10:00:16 GMT</lastBuildDate><pubDate>Sun, 12 Apr 2026 10:00:16 GMT</pubDate><ttl>60</ttl><item><title>儿童节到了</title><link>http://www.blogjava.net/nan306635934/archive/2010/06/01/322435.html</link><dc:creator>home_here</dc:creator><author>home_here</author><pubDate>Tue, 01 Jun 2010 04:35:00 GMT</pubDate><guid>http://www.blogjava.net/nan306635934/archive/2010/06/01/322435.html</guid><wfw:comment>http://www.blogjava.net/nan306635934/comments/322435.html</wfw:comment><comments>http://www.blogjava.net/nan306635934/archive/2010/06/01/322435.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nan306635934/comments/commentRss/322435.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nan306635934/services/trackbacks/322435.html</trackback:ping><description><![CDATA[多想有个孩子啊
<img src ="http://www.blogjava.net/nan306635934/aggbug/322435.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nan306635934/" target="_blank">home_here</a> 2010-06-01 12:35 <a href="http://www.blogjava.net/nan306635934/archive/2010/06/01/322435.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>精简JRE</title><link>http://www.blogjava.net/nan306635934/archive/2010/05/31/322321.html</link><dc:creator>home_here</dc:creator><author>home_here</author><pubDate>Mon, 31 May 2010 02:03:00 GMT</pubDate><guid>http://www.blogjava.net/nan306635934/archive/2010/05/31/322321.html</guid><wfw:comment>http://www.blogjava.net/nan306635934/comments/322321.html</wfw:comment><comments>http://www.blogjava.net/nan306635934/archive/2010/05/31/322321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nan306635934/comments/commentRss/322321.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nan306635934/services/trackbacks/322321.html</trackback:ping><description><![CDATA[<div class="postbody">Java开发程序，发布时总要考虑的问题就是怎么在使用者的机器上装好JRE。要考虑的问题很多：使用者有没有能力独自安装JRE，使用者已有的&nbsp;JRE&nbsp;和我们需要的版本是不是一致，会不会出现版本问题，等等。使用.NET要考虑的问题就少些。现在.NET&nbsp;CLR似乎已经很普及了，看好多D版的&nbsp;Win&nbsp;XP都会自己安装最新的.NET&nbsp;CLR，而且似乎它的安装界面也比JRE友好些。彻底解决安装JRE的问题的方案，就是让我们的应用程序自己背着JRE！这样，我们的程序就像传统的Win32应用程序一样，双击就可以执行，不用管所在的机器上是否有JRE，是什么版本的JRE，无论怎样，我有我自己的！要做到这一点，其实非常容易。<br />
王森在他的《Java深度历险》（强力推荐这本书，内容少而精）的第一章就解释了JDK，JRE，JVM之间的关系。解释了我们执行java.exe时发生的事情。其中提到，java.exe依照一套逻辑来寻找可以用的JRE，首先查找自己所在的目录下有没有&nbsp;JRE（据王森讲这样说不确切，我没有JDK全部的源代码，在此无从考证）；其次查找自己的父目录下有没有JRE；最后才是查询Windows的注册表。<br />
通常我们在安装好了JRE的机器上的任何一个目录下都可以执行java.exe。因为它在安装时被复制到了windows的system32目录下，而后者无论如何都会在path环境变量中。这个java.exe最终必然会访问注册表来确定真正的JRE的所在地。若我们要求每一个应用程序都自带JRE，必然不能走这条路。但，逻辑的第二条讲，java.exe会在它的父目录下查找JRE，解决方案就在这一条中。<br />
假设我们的应用程序打好了包，叫做&nbsp;MyApp.jar，放在MyApp的目录下。我们在MyApp目录下，可以执行java&nbsp;?jar&nbsp;MyApp.jar来运行我们的程序。我们安装的是&nbsp;JRE&nbsp;1.5，在C:\Program&nbsp;Files\Java\jre1.5.0下。现在，我们只需要简单的将jre1.5.0目录搬到MyApp目录下，顺便改个容易写的名字比如叫jre。现在，我们的应用程序就象这样：<br />
MyApp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyApp.jar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Jre<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Jre1.5.0目录下的全部内容<br />
Java.exe&nbsp;就在jre目录下的bin目录中。根据第二条逻辑，java.exe会在它的父目录中查找jre，实验证实，它会查找lib目录，而lib就在jre目录下。因此，这样java.exe就会确定jre的所在然后正常执行java程序，不会去管我们是否安装了JRE，注册表中是否有注册项这些杂事了。<br />
试一下，在命令行下进入MyApp的目录下，假设它在C盘，将path指向MyApp下的JRE：<br />
set&nbsp;path=c:\MyApp\jre\bin<br />
然后运行：<br />
java&nbsp;?verbose&nbsp;?jar&nbsp;MyApp.jar<br />
加上verbose参数以确定我们确实用了这一套被搬出了家的JRE。<br />
程序可以运行，并且在命令行输出的前几行，可以看到：<br />
[Opened&nbsp;C:\MyApp\jre\lib\rt.jar]<br />
[Opened&nbsp;C:\MyApp\jre\lib\jsse.jar]<br />
[Opened&nbsp;C:\MyApp\jre\lib\jce.jar]<br />
[Opened&nbsp;C:\MyApp\jre\lib\charsets.jar]<br />
因此程序读取的确实是它的私有的JRE。<br />
至此，我们似乎完成了任务。但是现在我们的私有JRE仍不完美，缺点是太大。JRE&nbsp;1.5有接近70MB，作为我们的私有的JRE，好多内容都是可以抛弃的。Jre目录下的license都可以不要，bin下的执行文件只需要保留java.exe或者javaw.exe，lib下只要保留rt，jsse，&nbsp;jce，charsets几个库就可以了。除了i386和zi两个子目录外，其余的子目录都可以不要。Zi下只需要保留自己地区的子目录和其下的一些文件就可以。Lib下除了库之外的属性文件等等都要保留。这样清理一番，JRE仍然有接近50MB。还可以继续清理几个库文件里面不需要的内容，这需要仔细的整理，会很费功夫。最好能写出一个自动工具帮助我们整理它们。从Sun公司上下到的JMF里面附带的用Java写的媒体播放器就自带了JRE，只有几个&nbsp;MB。<br />
清理过后需要运行几遍我们的应用程序，以确保我们的JRE不缺少东西。<br />
如果我们希望能有一个程序直接启动我们的应用程序，那就还要费些功夫。最简单的方法是弄出一个快捷方式来，但是快捷方式的路径不能是相对的，不方便我们安装。我想到的方案就是用Win32程序包装一下。在VS.NET下写一个Win32小程序：<br />
int&nbsp;PASCAL&nbsp;WinMain(&nbsp;HINSTANCE&nbsp;hInstance,<br />
&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hPrevInstance,<br />
&nbsp;&nbsp;&nbsp;&nbsp;LPSTR&nbsp;lpszCmdLine,<br />
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;nCmdShow&nbsp;)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;STARTUPINFO&nbsp;si;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PROCESS_INFORMATION&nbsp;pi;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;ZeroMemory(&nbsp;&amp;si,&nbsp;sizeof(si)&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;si.cb&nbsp;=&nbsp;sizeof(si);<br />
&nbsp;&nbsp;&nbsp;&nbsp;ZeroMemory(&nbsp;&#960;,&nbsp;sizeof(pi)&nbsp;);<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Start&nbsp;the&nbsp;child&nbsp;process.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;!CreateProcess(&nbsp;"jre\\bin\\javaw.exe",//执行的程序名<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"jre\\bin\\javaw.exe&nbsp;-jar&nbsp;MyApp.jar",&nbsp;//&nbsp;带参数的执行程序<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Process&nbsp;handle&nbsp;not&nbsp;inheritable.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Thread&nbsp;handle&nbsp;not&nbsp;inheritable.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FALSE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Set&nbsp;handle&nbsp;inheritance&nbsp;to&nbsp;FALSE.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;No&nbsp;creation&nbsp;flags.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Use&nbsp;parent's&nbsp;environment&nbsp;block.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Use&nbsp;parent's&nbsp;starting&nbsp;directory.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;si,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Pointer&nbsp;to&nbsp;STARTUPINFO&nbsp;structure.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#960;&nbsp;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Pointer&nbsp;to&nbsp;PROCESS_INFORMATION&nbsp;structure.<br />
&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorExit(&nbsp;"CreateProcess&nbsp;failed."&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Wait&nbsp;until&nbsp;child&nbsp;process&nbsp;exits.<br />
&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(&nbsp;pi.hProcess,&nbsp;INFINITE&nbsp;);<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Close&nbsp;process&nbsp;and&nbsp;thread&nbsp;handles.&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(&nbsp;pi.hProcess&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(&nbsp;pi.hThread&nbsp;);<br />
}<br />
基本上是按照MSDN文档中的例子照搬的。将它编译成一个EXE文件，我们的任务才全部完成。双击这个EXE文件，我们的程序启动了，看起来和传统的Win32程序没有两样，JRE完全被隐藏在底层。<br />
</div>
<img src ="http://www.blogjava.net/nan306635934/aggbug/322321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nan306635934/" target="_blank">home_here</a> 2010-05-31 10:03 <a href="http://www.blogjava.net/nan306635934/archive/2010/05/31/322321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>