Linux環境部署項目引起Out of Memory Error: PermGen Space的解決方案


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的調優,明白各個參數的意義,以及調優的原理,大家有好的資源可以分享出來一起學習;然后就是多實踐了,光有想法是遠遠不夠的,多實踐才能總結出更多有用的東西,分享給大家。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM