欢迎光临
我们一直在努力

让Java程序自带JRE-JSP教程,Java技巧及代码

建站超值云服务器,限时71元/月

 

用java开发程序,发布时总要考虑的问题就是怎么在使用者的机器上装好jre。要考虑的问题很多:使用者有没有能力独自安装jre,使用者已有的jre和我们需要的版本是不是一致,会不会出现版本问题,等等。使用.net要考虑的问题就少些。现在.net clr似乎已经很普及了,看好多d版的win xp都会自己安装最新的.net clr,而且似乎它的安装界面也比jre友好些。彻底解决安装jre的问题的方案,就是让我们的应用程序自己背着jre!这样,我们的程序就像传统的win32应用程序一样,双击就可以执行,不用管所在的机器上是否有jre,是什么版本的jre,无论怎样,我有我自己的!要做到这一点,其实非常容易。
王森在他的《java深度历险》(强力推荐这本书,内容少而精)的第一章就解释了jdk,jre,jvm之间的关系。解释了我们执行java.exe时发生的事情。其中提到,java.exe依照一套逻辑来寻找可以用的jre,首先查找自己所在的目录下有没有jre(据王森讲这样说不确切,我没有jdk全部的源代码,在此无从考证);其次查找自己的父目录下有没有jre;最后才是查询windows的注册表。
通常我们在安装好了jre的机器上的任何一个目录下都可以执行java.exe。因为它在安装时被复制到了windows的system32目录下,而后者无论如何都会在path环境变量中。这个java.exe最终必然会访问注册表来确定真正的jre的所在地。若我们要求每一个应用程序都自带jre,必然不能走这条路。但,逻辑的第二条讲,java.exe会在它的父目录下查找jre,解决方案就在这一条中。
假设我们的应用程序打好了包,叫做myapp.jar,放在myapp的目录下。我们在myapp目录下,可以执行java –jar myapp.jar来运行我们的程序。我们安装的是jre 1.5,在c:\program files\java\jre1.5.0下。现在,我们只需要简单的将jre1.5.0目录搬到myapp目录下,顺便改个容易写的名字比如叫jre。现在,我们的应用程序就象这样:
myapp
       myapp.jar
       jre
              jre1.5.0目录下的全部内容
java.exe就在jre目录下的bin目录中。根据第二条逻辑,java.exe会在它的父目录中查找jre,实验证实,它会查找lib目录,而lib就在jre目录下。因此,这样java.exe就会确定jre的所在然后正常执行java程序,不会去管我们是否安装了jre,注册表中是否有注册项这些杂事了。
试一下,在命令行下进入myapp的目录下,假设它在c盘,将path指向myapp下的jre:
set path=c:\myapp\jre\bin
然后运行:
java –verbose –jar myapp.jar
加上verbose参数以确定我们确实用了这一套被搬出了家的jre。
程序可以运行,并且在命令行输出的前几行,可以看到:
[opened c:\myapp\jre\lib\rt.jar]
[opened c:\myapp\jre\lib\jsse.jar]
[opened c:\myapp\jre\lib\jce.jar]
[opened c:\myapp\jre\lib\charsets.jar]
因此程序读取的确实是它的私有的jre。
至此,我们似乎完成了任务。但是现在我们的私有jre仍不完美,缺点是太大。jre 1.5有接近70mb,作为我们的私有的jre,好多内容都是可以抛弃的。jre目录下的license都可以不要,bin下的执行文件只需要保留java.exe或者javaw.exe,lib下只要保留rt,jsse,jce,charsets几个库就可以了。除了i386和zi两个子目录外,其余的子目录都可以不要。zi下只需要保留自己地区的子目录和其下的一些文件就可以。lib下除了库之外的属性文件等等都要保留。这样清理一番,jre仍然有接近50mb。还可以继续清理几个库文件里面不需要的内容,这需要仔细的整理,会很费功夫。最好能写出一个自动工具帮助我们整理它们。从sun公司上下到的jmf里面附带的用java写的媒体播放器就自带了jre,只有几个mb。
清理过后需要运行几遍我们的应用程序,以确保我们的jre不缺少东西。
如果我们希望能有一个程序直接启动我们的应用程序,那就还要费些功夫。最简单的方法是弄出一个快捷方式来,但是快捷方式的路径不能是相对的,不方便我们安装。我想到的方案就是用win32程序包装一下。在vs.net下写一个win32小程序:

int pascal winmain( hinstance hinstance,
    hinstance hprevinstance,
    lpstr lpszcmdline,
    int ncmdshow )
{
    startupinfo si;
    process_information pi;
 
    zeromemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    zeromemory( &pi, sizeof(pi) );
 
    // start the child process.
    if( !createprocess( “jre\\bin\\javaw.exe”,//执行的程序名
                        “jre\\bin\\javaw.exe -jar myapp.jar”, // 带参数的执行程序
            null,             // process handle not inheritable.
            null,             // thread handle not inheritable.
            false,            // set handle inheritance to false.
            0,                // no creation flags.
            null,             // use parents environment block.
            null,             // use parents starting directory.
            &si,              // pointer to startupinfo structure.
            &pi )             // pointer to process_information structure.
    )
    {
            errorexit( “createprocess failed.” );
    }
 
    // wait until child process exits.
    waitforsingleobject( pi.hprocess, infinite );
 
    // close process and thread handles.
    closehandle( pi.hprocess );
    closehandle( pi.hthread );
}

基本上是按照msdn文档中的例子照搬的。将它编译成一个exe文件,我们的任务才全部完成。双击这个exe文件,我们的程序启动了,看起来和传统的win32程序没有两样,jre完全被隐藏在底层。

p.s. 使用了这个方案后,我用wise installation system制作安装程序,发现一个非常奇怪的问题,安装结束后,安装程序似乎非要运行一个叫做glj什么什么,后缀是tmp的程序,还需要jvm,结果就报错jvm.dll找不到。安装总是不成功。我已经禁掉了ocx / dll / exe自注册和卸载支持,为什么还不对?有谁知道是为什么吗?

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » 让Java程序自带JRE-JSP教程,Java技巧及代码
分享到: 更多 (0)