隨着服務器上的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
咱們能夠經過-xms和-xmax設定初始的和最大的永久存續區的內存大小。默認的永久存續期的初始內存爲物理內存的1/64,最大的內存爲1/4。若服務器操做系統爲32位時,不能永久存續區的最大內存不能超過2G,64位操做系統不受此限制。
web
雖然經過修改啓動tomcat的jvm內存參數,增大vm的堆內存來解決能夠解決這個問題,可是這個沒法根本解決這個問題。spring
咱們經過tomcat設定shared lib實現全部項目共享相同的jar類包,經過這種方式有兩個好處sql
一、避免各個項目重複加載相同的jar類包,佔用了大量的永續區的內存apache
二、提升了tomcat的啓動速度。由於減小了各個項目中的重複jar類包reload,tomcat的reload速度獲得提高。tomcat
打開進入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方式。
這個是由於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