tomcat中設置多項目共享jar;類包

      隨着服務器上的tomcat部署的項目愈來愈多,最近在部署一個新的項目的時候出現內存溢出的錯誤html

 

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
        at java.lang.StackTraceElement.equals(StackTraceElement.java:204)
        at java.lang.Throwable.printEnclosedStackTrace(Throwable.java:688)
        at java.lang.Throwable.printStackTrace(Throwable.java:666)
        at java.lang.Throwable.printStackTrace(Throwable.java:720)
        at java.util.logging.SimpleFormatter.format(SimpleFormatter.java:157)
        at java.util.logging.StreamHandler.publish(StreamHandler.java:196)
        at java.util.logging.ConsoleHandler.publish(ConsoleHandler.java:105)
        at java.util.logging.Logger.log(Logger.java:522)
        at java.util.logging.Logger.doLog(Logger.java:543)
        at java.util.logging.Logger.logp(Logger.java:743)
        at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:198)
        at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:151)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:648)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Exception in thread "Timer-1" java.lang.OutOfMemoryError: PermGen space
        at sun.misc.Unsafe.defineClass(Native Method)
        at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:63)
        at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399)
        at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:396)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:395)
        at sun.reflect.MethodAccessorGenerator.generateConstructor(MethodAccessorGenerator.java:94)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:48)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
        at java.lang.Class.newInstance0(Class.java:372)
        at java.lang.Class.newInstance(Class.java:325)
        at oracle.net.ns.NSProtocol.connect(NSProtocol.java:250)
        at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1042)
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:301)
        at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:531)
        at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:221)
        at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
        at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:503)
        at java.sql.DriverManager.getConnection(DriverManager.java:579)
        at java.sql.DriverManager.getConnection(DriverManager.java:221)
        at cn.com.pujiConvert.util.DbUtil.connect(DbUtil.java:37)
        at cn.com.pujiConvert.util.DbUtil.<init>(DbUtil.java:25)
        at cn.com.pujiConvert.dao.Document.getDocumentInfo(Document.java:33)
        at cn.com.pujiConvert.convert.ConvertDocumentToPdf.getDocInfo(ConvertDocumentToPdf.java:49)
        at cn.com.pujiConvert.convert.ConvertDocumentToPdf.getConvertPdfResult(ConvertDocumentToPdf.java:204)
        at cn.com.pujiConvert.timer.ConvertTimerTask.convertDocumentToPdfTask(ConvertTimerTask.java:16)
        at cn.com.pujiConvert.timer.ConvertTimerTask.run(ConvertTimerTask.java:49)
        at java.util.TimerThread.mainLoop(Timer.java:555)
        at java.util.TimerThread.run(Timer.java:505)

      以上提示說永久存續區的內存溢出。永久存續區的內存主要存儲和加載Class和Meta信息,垃圾回收器不會回收這一區域的內存,只會回收堆內存。如何解決上面的永久存續期內存溢出問題呢?主要有兩種方式java

 

      增大jvm的非堆內存

        咱們能夠經過-xms和-xmax設定初始的和最大的永久存續區的內存大小。默認的永久存續期的初始內存爲物理內存的1/64,最大的內存爲1/4。若服務器操做系統爲32位時,不能永久存續區的最大內存不能超過2G,64位操做系統不受此限制。
web

      經過tomcat設定shared lib目錄方式

        雖然經過修改啓動tomcat的jvm內存參數,增大vm的堆內存來解決能夠解決這個問題,可是這個沒法根本解決這個問題。spring

         咱們經過tomcat設定shared lib實現全部項目共享相同的jar類包,經過這種方式有兩個好處sql

一、避免各個項目重複加載相同的jar類包,佔用了大量的永續區的內存apache

二、提升了tomcat的啓動速度。由於減小了各個項目中的重複jar類包reload,tomcat的reload速度獲得提高。tomcat

       配置shared lib

       打開進入tomcat/conf/目錄。打開catalina.properties配置文件,修改兩個地方
服務器

一、找到shared.loader=位置,設置共享目錄地址oracle

 

shared.loader=${catalina.base}/shared/lib,${catalina.base}/shared/lib/*.jar

 

二、找到common.loader位置,並追加shared lib目錄地址
app

common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,${catalina.base}/shared/lib,${catalina.base}/shared/lib/*.jar

 

三、自行建立${catalina.base}/shared/lib,${catalina.base}/shared/lib/路徑,並將共享的jar類包放在該目錄下

     特別說明:jar共享目錄能夠在tomcat目錄下,也能夠自行定義一個絕對路徑。若是是相對路徑只能相對於${catalina.base}/。實現jar共享方式在以上shared.loader和common.loader中任選一種便可,不過我的傾向於使用shared.dir方式。

       補充:toncat類加載機制

 

  • Commonclassloader:負責裝載$CATALINA_HOME/common目錄下的全部類和jar包,詳細的配置可參考$CATALINA_HOME/conf/catalina.properties文件中的common.loader配置;該classloader裝載的類對於Server class loader和Webapp class loader是可見的;Commonclass loader在Tomcat啓動時建立,其parent classloader是System class loader;
  • Server classloader:負責裝載Tomcat的核心類,位於$CATALINE_HOME/server目錄下的全部類和jar,可由catalina.propreties中的server.loader配置指定;它在Tomcat啓動時被建立,其parent loader是Commonclass loader;
  • Sharedclass loader:負責裝載webapp公用的類,能夠用戶經過catalina.properties文件中的shared.loader屬性來指定;它在Tomcat啓動時被建立,其parentloader也是Common class loader;
  • Webappclassloader:這個比較特殊,它只負責加載各自app中WEB-INF/classes以及WEB-INF/lib下的類;其parentloader雖然是Shared class loader,但其加載策略和默認的類加載機制不太同樣;

 

       No Spring WebApplicationInitializer types detected on classpath

         這個是由於spring 3.1之後在加載前會自動先掃描,查找WebApplicationInitializer的實現類

 

 

    <listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener> 
    <context-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

         若是自行定義加載,不須要自動掃描,能夠經過metadata-complete="true"關閉自動掃描

    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    metadata-complete="true"> 

 

       參考資料

         一、http://blog.sina.com.cn/s/blog_4db5ab6701013kuw.html

         二、http://blog.csdn.net/java_wliang/article/details/18044507

相關文章
相關標籤/搜索