Jetty虽然是Java编写的程序,可以跨平台使用,但需要java虚拟机来启动,而java虚拟机并不是跨平台的,要重新寻找一个能在linux系统中使用且占用空间尽可能小的java虚拟机。由于arm只提供最多52M的空间,所以不得不排除我们最常用的sun公司的jre,因为它的安装目录达到134M,大大超过可用空间,裁剪工作也不太容易。
经过查找资料,基本确定以下几种方案:
1)CVM + jetty5
SUN公司的J2ME是专为移动设备设计的,在移动通信设备上已经有广泛的应用,很适合在嵌入式中使用。CVM是一个具有完整的J2SE L3 VM支持能力的Java虚拟机,但又比标准的J2SE VM小。作为一个全功能的Java虚拟机,CVM几乎支持J2SE VM的所有先进特性,包括最底层的调错处理和本地语言接口。
2)Android + i-jetty
i-jetty是google公司基于jetty开发的运行在Android平台上的web容器,使手机也能搭建web服务。
3)Jamvm + GNU classpath + jetty5
Jamvm是一个c语言编写的开源的java虚拟机,它使用GNU classpath作为java类库。
首先采用第一种方案,具体操作过程见我的另一篇文章,这里只想说明结果。在对arm平台的CVM进行测试后发现,自带的HelloWorld和Test程序输出结果正常,但是启动jetty就会出现java.lang.UnsatisfiedLinkError异常,根据出错提示查看类库确实缺少很多类。后来使用裁剪的rt.jar仍然出现异常,看来CVM只适合小应用程序,对jetty这种比较大型的网络程序不太适合。
第二种方案没有过多去研究就否定了,我们的arm板运行的是linux,不可能更换成Android,如果想要使用i-jetty就得安装Android模拟器,可是该模拟机占用空间不小,也就没有花费太长时间去尝试。
第三种方案是研究时间最长,最有可能实现的方案了。虽然arm板上已有linux,但由于硬件限制不能在其上编译程序,所以还要准备其他的主机来完成编译工作,然后再将文件复制到arm板上。起先使用同事给我的Redhat Linux虚拟镜像,但是无论怎样编译classpath都编译不过。网上查找了很多有关这方面的资料,都没有人在Redhat下编译jamvm + classpath成功的例子,倒是在Ubuntu下成功过。于是自己在VMware中安装了Ubuntu 8.04服务器版的虚拟镜像(可从项目服务器下载),经过几天时间的编译、调错,终于找出能够编译成功的版本组合。
下面主要讲解的编译环境和操作过程就是基于第三种方案jamvm + GNU classpath。
编译环境及工具
Ubuntu 8.04虚拟镜像
项目服务器上的镜像,已安装了编译所需的其他工具如gcc、zlib、gcj、ecj等, 如果使用其他Ubuntu版本,需在编译时根据提示安装相应的程序。
Arm交叉编译链 4.3.2
提供的虚拟镜像中已经安装好,不需再安装,用来编译arm平台上运行的c和c++程序。
GNU Classpath 0.93
Jamvm使用的java类库,需要交叉编译。
Jamvm 1.5.1
一个开源的java虚拟机,需要交叉编译。
Jetty 5.1.12
Java编写的开源web容器,不需要交叉编译。
我们大部分工作都是在虚拟机中完成的,包括编译、打包、测试等等,虽然在arm上运行和虚拟机上运行结果有可能不尽相同,但经过我的运行测试发现,在arm上运行不了而出错的话,在虚拟机中运行出现同样的错误,所以一般我都会在虚拟机中调试好,程序能够运行再放到arm板,这样成功率更大。
工作目录 \home\kiki\work
Arm交叉编译链、GNU Classpath、jamvm和jetty5源程序都存放在work工作目录下,环境变量中需指定arm交叉编译链的路径。
目标目录 \tmp
为了能与arm平台的目标目录相同,使用tmp文件夹作为编译的目标文件夹。用来存放GNU Classpath和jamvm编译后的文件,需要在configure时指定目标路径。
Classpath 0.9.3 + jamvm 1.5.1 这是我测试过,能编译成功的版本组合,但可能并不是唯一的。由于操作系统和安装软件不全的关系,在别人的Ubuntu上匹配的版本组合在我这里却不行,可是公司网速慢啊,在线安装软件不太可行,勉强安装好必须的软件,下面就使用这个组合吧。
编译Classpath
① $ tar zxf classpath-0.93.tar.gz
解压缩Classpath 0.93
② $ cd classpath-0.93
进入classpath文件夹
③ $ ./configure --prefix=/tmp/classpath --disable-gtk-peer --disable-gconf-peer --disable-plugin --with-ecj --host=arm-linux
检查classpath所需的编译环境,生成makefile文件
--prefix 最终编译文件的目标路径。
--host 目标程序运行平台,arm-linux表示编译成arm平台程序,省略这个参数表示编译成x86平台程序。
--disable-gtk-peer
--disable-gconf-peer
--disable-plugin
系统中缺少这几个程序,添加这三个参数使编译能够通过。
④ $ make
编译
⑤ $ make install
编译安装
⑥ 复制/tmp/classpath整个文件夹到目标板的/tmp目录下,也可以先打包,在arm上再解压。
编译Jamvm
① $ tar zxf jamvm-1.5.1.tar.gz
解压缩jamvm-1.5.1
② $ cd jamvm-1.5.1
进入jamvm文件夹
③ $ ./configure --prefix=/tmp/jamvm --with-classpath-install-dir=/tmp/classpath –host=arm-linux
--with-classpath-install-dir jamvm运行时调用java类库的路径
④ $ make
编译
⑤ $ make install
编译安装
⑥ 复制/tmp/jamvm整个文件夹到目标板的/tmp目录下
⑦ $ vi /etc/profile
设置环境变量,修改PATH内容,PATH=$PATH:/tmp/jamvm/bin
⑧ $ . /etc/profile
保存环境变量使之立即生效,运行jamvm命令看看,出现帮助说明环境变量已经设置成功。
裁剪Jetty 5.1.12
Jetty在启动时会生成临时文件,需要频繁读写文件,这样会直接影响arm平台,导致flash卡上的文件不能删除,不得不重新做卡。所以jetty-5.1.12.zip这个文件不能解压到/tmp下,只能解压到/home目录下,这里是内存,允许频繁读写。但由于jetty程序指定了在系统临时文件夹下创建临时文件,而linux的临时文件夹就是/tmp目录,查找资料发现如果在jetty工作目录下创建一个work目录的话,程序就会在work目录下生成临时文件,这样就不会影响系统的/tmp目录了。
为了节约空间,对jetty的源码包做裁剪,删除启动过程中用不到的文件。经过反复测试,以下目录可以删除:
\demo
\javadoc
\jsp_src
\src
\test
\testdocs
\webapps\template
另外在zip包中添加work空文件夹,以免解压后忘记创建它,后果很严重!上传裁剪好的jetty.zip到arm板/tmp目录下,然后解压到/home目录下,注意/home是内存,所以重启后内容清空,需重新解压。
启动Jetty5
① 进入/home/jetty-5.1.12文件夹
② 命令行方式启动
jamvm -Djavax.net.ssl.trustStore=etc/mytruststore -Djavax.net.ssl.trustStorePassword=11111111 –jar start.jar
可能出现的问题及解决方法
- configure error : C compiler cannot create executables
可能gcc编译环境没配好,直接sudo apt-get install gcc libc6-dev就可以解决,但需要联网下载所需的文件。
- 启动jetty出现java.lang.NoClassDefFoundError: java/util/concurrent/ConcurrentHashMap异常
重新编译Classpath,首先更改目标路径/tmp/classpath1,参数中去掉—host=arm-linux,然后make和make install,打开\tmp\classpath1\share\classpath\glibj.zip,将java/util/concurrent整个文件夹拖动到\tmp\classpath\share\classpath\glibj.zip,最后替换arm板的glibj.zip文件。
- 启动jetty出现java.lang.NoClassDefFoundError: org/mortbay/util/ArrayQueue,Caused by: java.lang.NoClassDefFoundError: java/util/Queue异常
解决方法同上,把x86平台的glibj.zip中的Queue.class文件放到arm平台的glibj.zip,然后替换arm板上的文件。
- 启动jetty出现java.security.NoSuchAlgorithmException: Algorithm [SunX509] of type [KeyManagerFactory] from provider [gnu.javax.security.auth.callback.GnuCallbacks: name=GNU-CALLBACKS version=2.1] is not found
该问题由于取消etc/jetty.xml中有关ssl服务的注释导致,通过测试程序TestSunX509得知jetty默认使用jks的keystore和SunX509算法都不能用,修改jetty.xml,在ssl服务段中加入以下几行代码
<Set name="Algorithm">JESSIEX509</Set>
<Set name="KeystoreType">GKR</Set>
修改<Set name="Password">11111111</Set>
修改<Set name=" KeyPassword">11111111</Set>
进入etc文件夹,依次执行以下命令:
keytool –genkey –alias localhost –keystore mykeystore
keytool –genkey –alias localhost –keystore mytruststore
按照提示输入字符即可创建GKR格式的keystore和truststore,密码都为8个1。
- 启动jetty出现java.security.KeyStoreException: java.io.FileNotFoundException: /tmp/jamvm/lib/security/cacerts异常
启动jetty的命令改成jamvm -Djavax.net.ssl.trustStore=etc/mytruststore -Djavax.net.ssl.trustStorePassword=11111111 -jar start.jar,而不是简单的jamvm –jar start.jar。
执行命令sudo apt-get install confluence
- configure: error: zlib is missing
下载zlib-1.2.3.tar.gz进行编译安装。
WARN!! [Acceptor ServerSocket[addr=/127.0.0.1,port=8081,localpor
t=8081]] org.mortbay.util.ThreadedServer$Acceptor.run(ThreadedServer.java:648
) >01> EXCEPTION
java.lang.NullPointerException
at gnu.java.net.PlainSocketImpl.accept(PlainSocketImpl.java:342)
at java.net.ServerSocket.implAccept(ServerSocket.java:391)
at java.net.ServerSocket.accept(ServerSocket.java:333)
at org.mortbay.util.ThreadedServer.acceptSocket(ThreadedServer.java:432)
at org.mortbay.util.ThreadedServer$Acceptor.run(ThreadedServer.java:634)
原因还不明,此时浏览器已经可以访问8080端口的http服务。
附1:本人测试成功的版本组合
Red Hat Enterprise Linux 4
内核 2.6.9- 5.EL
gcc 3.4.3
classpath 0.93
jamvm 1.5.1
Ubuntu 8.04
内核 2.6.24-24 generic
gcc 4.2.4
classpath 0.96
jamvm 1.5.1
附2:更改jetty生成临时文件目录
Jetty在启动一个Web应用程序的时候,会按照以下顺序来决定当前应用的临时文件目录(javax.servlet.context.tempdir):
>通过WebAppContext.setTempDirectory设置的临时文件目录
>上下文中已经定义的javax.servlet.context.tempdir所对应的目录
>${jetty.home}/work目录
>WEB-INF/work目录
>${java.io.tmpdir}目录
在通过上述方式定位到一个目录后,Jetty会在其中按照jetty_host_port_virtualHost_contextPath_hash的格式创建一个子目录,并把该子目录作为临时文件目录注册给javax.servlet.context.tempdir。
这里面需要注意的是,除了第一种(并且仅当该目录为Jetty创建的前提下)和最后一种使用场景下Jetty会在Web应用程序退出以后自动删除临时目录以外,其余场景Jetty都会保留临时文件目录。这就意味着,如果在同一目录下部署应用程序的新版本,那么很有可能会出现文件版本不一致的问题!请大家在使用的时候要格外小心。
附3:裁剪jetty6
经过在虚拟机上测试,以下目录占用较大空间且不是必要的,可以进行删除。
\examples
\javadoc
\modules
\lib\jsp-2.0
\lib\management\mx4j
\webapps\test-jaas
附4: 查看是否支持SunX509的java程序
Java代码
import java.security.Security;
public class TestSunX509 {
public static void main(String[] args) {
if(args.length >0 && args[0].equals("1")){
Security.setProperty("ssl.KeyManagerFactory.algorithm", "SunX509");
}
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
if (algorithm == null) {
System.out.println("algorithm is null");
}else{
System.out.println("algorithm is " + algorithm);
}
}
}
windows和redhat中输出algorithm is SunX509
ubuntu中输出algorithm is null
打印结果验证了我的想法。那么ubuntu中到底有哪些算法呢?我把测试程序做下改进,在main方法中添加下面这段代码,使之能够输出Provider及algorithm。
Java代码
Provider[] providers = Security.getProviders();
int cnt = 1;
for(Provider p : providers){
System.out.println(cnt ++ + " : " + p.getName());
for (Enumeration e = p.keys(); e.hasMoreElements();){
System.out.println("\t" + e.nextElement());
}
}
原来ubuntu的provider中没有SunJSSE,只有GNU、GNU-CRYPTO、GNU-SASL、Jessie和GNU-CALLBACKS,都是开源的。
解决找不到SunX509的问题有2种方法:
一种是修改classpath/lib/security/classpath.security,添加一行ssl.KeyManagerFactory.algorithm=JESSIEX509;另一种是修改jetty.xml,在打开ssl监听这段的后面添加<Set name="Algorithm">JESSIEX509</Set>,推荐使用后一种方法,原因下面会说到。
再次启动jetty5,出现java.security.KeyStoreException: JKS异常,
Caused by: java.security.NoSuchAlgorithmException: Algorithm [JKS] of type [KeyStore] from provider [gnu.javax.security.auth.callback.GnuCallbacks: name=GNU-CALLBACKS version=2.1] is not found
at gnu.java.security.Engine.getInstance(Engine.java:189)
at gnu.java.security.Engine.getInstance(Engine.java:103)
at java.security.KeyStore.getInstance(KeyStore.java:188)
...17 more
这次很快就找到原因了,jks是sun java的证书格式,而GNU classpath的证书格式是GKR。尝试在classpath.security文件中添加keystore.type=GKR,异常仍然存在,所以刚才我不推荐这种方法。同样,还是修改jetty.xml,在刚才添加JESSIEX509一行的下面添加<Set name="KeystoreType">GKR</Set>,问题解决。
再次启动jetty5,出现gnu.javax.crypto.keyring.MalformedKeyringException: incorrect magic异常,虽然keystoretype改成了GKR格式,但是默认的demokeystore仍然是jks格式,自己使用GNU的keytool生成一个mykeystore来代替demokeystore,并修改jetty.xml中的Keystore路径和Password、KeyPassword。
再次启动jetty5,出现java.security.KeyStoreException: java.io.FileNotFoundException: /tmp/jamvm/lib/security/cacerts异常,因为找不到TrustStore,这次修改jetty.xml是没用的,因为org.mortbay.http.SslListener.java中没有setTrustStore方法,但可以用参数赋值的方法指定truststore。
启动时的命令:jamvm -Djavax.net.ssl.trustStore=etc/mytruststore -Djavax.net.ssl.trustStorePassword=11111111 -jar start.jar
这次终于成功启动jetty,并且http和https服务都在,8443端口也打开ssl监听,浏览器可以访问8080的http服务,但是8443的https却没有响应,不知道是为什么,哪位大侠知道原因请指点一下小妹儿,感激不尽!
分享到:
相关推荐
内容概要:本博客系统主要使用Jetty技术+Servlet技术+Jsp技术+BootStrap前端框架+wangEditor富文本编辑器+MySQL数据库+MyBatis持久层,通过对该系统的设计,可以在实践过程中掌握相关基础知识,如对三层架构开发模式...
利用maven搭起的Spring MVC+Mybatis框架,并带有数据库表结构,使用者可直接导入mysql使用,有主外键关系
spring mvc3.2.7(基于注解配置)+servlet3.1(jetty)+maven3+eclipse
码头休息区 jettyREST 是关于如何使用 Jetty + JAX-RS + Jersey + Servlet 3.0 作为 RESTful API 的技术堆栈的示例。 它非常基础,仅包含一个简单的设置脚手架... 如果在本地主机上运行,您可以在此处查看示例:
jetty9资源通过官网下载实在太慢,为了国内程序员快速获得jetty资源,特别上jetty在idea编译器上的配置教程。
导入即可运行,包括下面jar。 jar包: cometd-api-0.9.20080221 cometd-bayeux-6.1.9 jetty-6.1.9 jetty-util-6.1.9 servlet-api-2.5-6.1.9 全网搜索dojox.cometd实现WEBQQ,没有可以运行的源码包项目,搞了五天,...
websocket+tomcat+jetty+netty
一键部署demo+jetty+svn+ant配置
maven+jetty 的ssh框架例子 直接运行 run:jetty
NULL 博文链接:https://caerun.iteye.com/blog/1145451
Maven原型在Spring Boot上使用Jetty + Jersey + Jackson + MessagePack创建现代Java RPC堆栈 如何使用 与重击 mvn archetype:generate\ -DarchetypeGroupId=am.ik.archetype\ -DarchetypeArtifactId=msgpack-rpc-...
想直接通过域名活ip访问xacs或者准备集群配置的童鞋,往这看
https://github.com/jetty-project/i-jetty下载的源码,移植到Android studio
jetty是一个轻便的嵌入式servlet容器。其启动运行非常简单。这是一个简单的Jetty例子程序。
此项目用作示例存储库,其中包含有关如何使用 Jersey 作为 JAX-RS 提供程序快速设置带有 REST 端点的 Jetty 服务器的示例。 运行示例 运行 com.labs2160.example.JettyApp 类。 mvn clean compile exec:java 然后...
一个插件,允许您从IntelliJ IDEA快速运行Jetty
JOnAS5里的Jetty 配置Ajax、Comet和异步Servlets 持续和异步Servlets 100 Continue和102 Processing WebSocket Servlet 异步的REST Stress Testing CometD 使用Servlets和Filters Jetty中绑定的Servlets Quality of...
Eclipse+ jetty+android+websocket协议整合 这里介绍了怎么安装jett插件,共享了一个jett服务器demo,简要介绍了如何配置服务器,同时还给了一个android的客户端。对于android客户端发送websocket协议数据:要注意...
jetty服务器性能调整过程分析jetty服务器性能调整过程分析jetty服务器性能调整过程分析jetty服务器性能调整过程分析
包括org.eclipse.jetty.servlet_7.1.6.v20100715.jar、org.eclipse.jetty.server.jar、org.eclipse.jetty.servlet.source_7.1.6.v20100715.jar三个jar包,在进行jetty嵌入式编程时需要用到。