1. 背景
前几天,在搭建项目时遇到到一些问题,现在整理记录一下。
Linux环境:Red Hat Enterprise Linux Server release 6.4;
# 查看命令
cat /etc/issue
JDK版本:jdk1.7.0_80;
Tomcat版本:apache-tomcat-7.0.79;
2.经过
由于之前曾使用Tomcat容器部署过项目,所以没有觉得有什么特别值得注意的地方,就是将web项目打成war包,放到Linux服务器tomcat容器下,然后启动Tomcat就OK了。
然而,现实并不如想象的那么顺利。。。
之前的部署是这么做的:Eclipse将web项目Export转成war,然后使用Xshell将该war包传至服务器(使用szrz命令,或其他传输工具),将war包放到Tomcat目录下的webapps下,然后回到tomcat目录下的bin目录,./start.sh,回车,整个工作就结束了。
现在的IDE用的是idea,网上各种搜idea下怎么将web项目打成war,一看过程要设置好多事项,果断放弃,想着直接用Linux命令搞定:
jar -cvf demo-web.war ./demo-web
开始看需要部署的项目,从SVN上下载下来一看,喔,19个项目,之前都是一个war包搞定的呀,19个毫不犹豫看了下总共要2-3G,然后找了一个(WinSCP)工具开始上传,局域网按说应该好快的,可能是由于无线的原因吧,愣是传了2,3个小时。传上去之后,打war包,移到webapps目录下,启动tomcat,然后结果是这样的:
严重: Error waiting for multi-thread deployment of directories to complete java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:188) at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:1198) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:530) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1749) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:370) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:388) at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:333) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1136) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:819) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1571) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1561) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:800) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:3205) at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:1373) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1861) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1735) at org.apache.catalina.util.Introspection.loadClass(Introspection.java:143) at org.apache.catalina.startup.ContextConfig.checkHandlesTypes(ContextConfig.java:2182) at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2120) at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:1981) at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1942) at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1927) at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1332) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:888) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:388) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5522) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:875) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652) at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1296) at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:2038) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) ... 4 more
一下愣住了,怎么会出现这个OutOfMemoryError,又重新试了几次,毫无例外,每次都是到这块报错OutOfMemoryError,看来只能是因为项目类太多,导致JVM内存被占满了,这个JVM的参数在哪里修改呢?百度了一下,基本可以确认需要更改的文件:tomcat/bin/catalina.sh,对就是tomcat的启动脚本文件,修改如下:
# OS specific support. $var _must_ be set to either true or false. JAVA_OPTS = "-Xms256m -Xmx512m -Xss128K -XX:PermSize=128m -XX:MaxPermSize=256m"
这下,应该好了吧,再来一次,结果丝毫没有改变,是不是改错地方了,又在网上找了一会儿,试了试这个方案:修改jdk/jre/lib/security/java.security这个文件原来内容为:
securerandom.source=file:/dev/urandom
修改为:
securerandom.source=file:/dev/./urandom
重启来一次,还是不行。看看快一天了,不行呀,赶紧问下老大,还是这个catalina.sh这个参数设置的问题,然后又回来各种尝试,把”-Xms -Xmx -XX:PermSize -XX:MaxPermSize“各种调大,各种尝试,依然没有进展,好吧,这次先把18个项目删掉只留一个,一试,哦,这下可以了,好吧,继续增加项目个数2个,3个,。。。,8个,就8个了,8个项目就启动不了了,还是java.lang.OutOfMemoryError: PermGen space;这就奇怪了,看看服务器内存占用和CPU使用情况吧:
[root@sv08 ~]# free total used free shared buffers cached Mem: 8061572 7893692 167880 0 454860 4351972 -/+ buffers/cache: 3086860 4974712 Swap: 8208376 21600 8186776
[root@sv08 ~]# top
这个看的还是有一定余量的,那只能是JVM参数的设置的问题了,继续网上找,试了几个修改catalina.properties和其他基本配置文件的方案,依然不起任何作用。
这时候同事过来帮忙了,说是之前遇到过类似问题,然后开始对比,-Xms,-Xmx与系统硬件占用情况,依然是top命令和free命令,结论是有富余,然后这是各种调catalina.sh的参数,没有任何效果,然后又开始注释项目代码,这类问题也可能与代码有关的了,然而,多次尝试之后也没有好的效果。
问题总得解决呀,眼下也没有什么好的办法,多尝试尝试吧,又继续尝试网上得方案, 各种试,终于,这样试了一下:
# OS specific support. $var _must_ be set to either true or false. JAVA_OPTS="-server -XX:PermSize=256m -XX:MaxPermSize=512m"
这个方案一试之后,8个项目可以启动了,呃呃,毫不犹豫,19个项目一起上,结果又出现了这个java.lang.OutOfMemoryError: PermGen space,尝试这个把后面俩个参数调大一倍,最终设置:
# OS specific support. $var _must_ be set to either true or false. JAVA_OPTS="-server -XX:PermSize=512m -XX:MaxPermSize=1024m"
./start.sh,启动成功!
参考链接:
https://blog.csdn.net/kongls08/article/details/8468713
3.总结
这个没有太多要说的,还是要多掌握下JVM的调优,明白各个参数的意义,以及调优的原理,大家有好的资源可以分享出来一起学习;然后就是多实践了,光有想法是远远不够的,多实践才能总结出更多有用的东西,分享给大家。