这几天一直在搞基于jnlp的java程序更新。搞得是晕头转向,手忙脚乱。呵呵,楼主技术比较菜。
还好,马马虎虎算是搞出来了。
其中遇到不少问题,拿出来和大家分享分享,避免以后大家再走弯路。
概念性的东西就不做解释了。
Java web start 百度百科给的很好。
jnlp 百度百科给的也很好,呵呵。大家可以看下他的定义。
http://baike.baidu.com/link?url=CFeRYNKm2eMu24Lsi5stTfxKbCaV33GCQsq84FNIsqmi0D4aEhDTmk5URi341pHz
楼主理解的Java web start其实就是应用程序部署到浏览器里面,看似是B/S程序,其实是C/S架构(可能理解不对,欢迎指正)。当然Java web start也可以拿出来单独运行。主要就是方面。比传统C/S少了很多安装步骤,比传统B/S多了更好的用户体验,而且可以时刻保存其最新的版本等。
jnlp这个就比较好了。这个东西给楼主的感觉就像是一个快捷方式,这个快捷方式可以指向服务器端的引用。以至于以后如果有软件更新,直接让用户更新一下这个jnlp文件就可以了。jnlp文件非常之小,一般只有几KB。这样的话就大大节省时间,非常提高用户的体验。这样,只需要更新一下服务器端的最新程序,然后让jnlp文件指向这个打好的jar包或者jnlp文件就OK了。
闲话扯了不少。
下面详细说说做这个更新的时候遇到的问题。
这个问题多半就是打包问题。打包签名的安全问题。
写好的项目需要达成jar包和jnlp文件。
楼主打包使用的是ant打包,没有使用现下比较流行的maven。至于为什么,楼主只能说,领导的世界我们不懂。
客户端使用的javafx,需要将客户端打成jar包。类似applet,使用javafx部署这种客户端,因为java的安全策略,java应用程序环境的安全策略,它是由一个Policy对象来表达。
我们需要手动的改一下Java\jre7\lib\security\java.policy文件。我在最后添加了一行permission java.security.AllPermission; 这就是给客户机所有的权限。这样一来,客户端程序就有权限来操作本地的权限。
再有就是需要对客户端程序的jar包进行数字签名。
数字签名:采用加密技术来实现对签名者身份的认证和数据的完整性。简单的说就是你签字的文件别人知道是你签的,并且知 道这个文件是否被修改过。
ant有signjar,使用这个标签给jar包进行签名。java自带的keytool.exe工具也可以实现签名,具体操作请自行查询。
具体错误:
java.lang.ExceptionInInitializerError
at javax.swing.filechooser.FileSystemView.getFileSystemView(Unknown Source)
at com.platform.ui.update.DownloadFileController.init(DownloadFileController.java:166)
at com.platform.ui.update.DownLoadFileView.buildInit(DownLoadFileView.java:41)
at com.platform.ui.update.MainUpdate.start(MainUpdate.java:17)
at com.sun.javafx.applet.FXApplet2$1.run(FXApplet2.java:132)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at javax.swing.SwingUtilities.appContextGet(Unknown Source)
at javax.swing.UIManager.getLAFState(Unknown Source)
at javax.swing.UIManager.maybeInitialize(Unknown Source)
at javax.swing.UIManager.getDefaults(Unknown Source)
at javax.swing.UIManager.getString(Unknown Source)
at javax.swing.filechooser.WindowsFileSystemView.<clinit>(Unknown Source)
... 13 more
Exception in runnable
java.lang.RuntimeException: java.lang.ExceptionInInitializerError
at com.sun.javafx.applet.FXApplet2$1.run(FXApplet2.java:148)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ExceptionInInitializerError
at javax.swing.filechooser.FileSystemView.getFileSystemView(Unknown Source)
at com.platform.ui.update.DownloadFileController.init(DownloadFileController.java:166)
at com.platform.ui.update.DownLoadFileView.buildInit(DownLoadFileView.java:41)
at com.platform.ui.update.MainUpdate.start(MainUpdate.java:17)
at com.sun.javafx.applet.FXApplet2$1.run(FXApplet2.java:132)
... 8 more
Caused by: java.lang.NullPointerException
at javax.swing.SwingUtilities.appContextGet(Unknown Source)
at javax.swing.UIManager.getLAFState(Unknown Source)
at javax.swing.UIManager.maybeInitialize(Unknown Source)
at javax.swing.UIManager.getDefaults(Unknown Source)
at javax.swing.UIManager.getString(Unknown Source)
at javax.swing.filechooser.WindowsFileSystemView.<clinit>(Unknown Source)
... 13 more
这种异常一般都是由于静态变量初始化失败造成,楼主在调用
FileSystemView.getFileSystemView
上面这行代码,调用这个静态方法的时候,程序初始化失败了。这个问题是在测试的时候出现在一个同事的电脑上,于是想到可能不是程序的问题,而是本地电脑环境的问题。于是想到了缓存,如果有缓存存在也可能会导致静态变量初始化失败的情况,清了缓存之后还是不可以,这个问题纠结纳闷了好久。最后发现是jre版本的问题。当时开发的时候都统一了版本,这种情况比较纠结,呵呵。可以肯定的是,版本不一样导致getFileSystemView这个静态方法初始化失败,至于为什么会这样,楼主还在研究当中。
这是在客户那里演示的时候出现的问题,当时比较尴尬了。
看到这个error感觉很致命,程序直接崩了。回来之后测试了N遍也没能重现这个问题,于是远程到客户电脑上看到底怎么回事,也在网上查了。大体都是在说内存不够,导致程序运行不起来。顺便吐槽一下部分程序员,直接就是搬运工,楼主搜了至少10几篇文章都是一个样。。也没标注转载。
于是楼主看了下客户的电脑配置,4G内存,CPU也很空闲。楼主自身电脑也是4G内存,跑这程序刷刷的。又限入无限纠结中,到底怎么回事呢。楼主想到了配置java运行参数的几个地方。比如Xsms,Xsmx之类。先是检查了环境变量的配置。没有问题。然后是jnlp文件的配置(jnlp文件里面有关于java运行内存的配置),也是没问题。最后终于发现问题所在!
在java的控制面板里面,有一项运行时参数,不填写或者填写的大一些,这样就可以运行了。这里限制java的运行环境。
这几个是主要问题,现在回头来看,其实也不是那么难,但在当时真是把楼主折腾的够呛。所谓不识庐山真面目,只缘身在此山中把。楼主深陷其中,一直不得所悟,呵呵。
还有一些显示不了的问题,都是一下小问题。比如把java的安全等级调低。
在调试客户端错误时,有必要将java控制台显示出来,并打印日志等信息。
坦言讲,楼主对于jnlp、javafx以及java web start的理解并不多么深刻,只是最近项目需要,临时研究了下。遇到一些问题和大家分享,希望能够帮助看到的人少走些弯路。如有不对,欢迎指正。QQ:70747053