最近,当我在windows开发环境下用tomcat 6.0.32部署一个web应用程序时,我得到了以下PermGen Space错误。
所以我想写一篇关于这个问题的文章,包括根本原因和异常情况。
Caused by: java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
到底是什么原因导致OutOfMemoryError?
这个问题要么发生在你的应用程序的启动阶段,要么发生在应用程序的运行阶段。
其中一个原因是
如你所知,java对象存储在堆内存中,当你的应用战争被部署并在tomcat容器中启动时,应用程序加载所有的对象,并调用启动来回调对象并加载到内存中,所以没有足够的内存来容纳内存中的所有对象。默认情况下,tomcat为进程分配了256m的堆内存,所以你必须根据你的应用程序的大小以及你的RAM容量来增加这个大小。
另一个原因是
JVM会自动清理对象,但有些对象会长期保留在内存中,每当你的应用程序启动/停止或你的应用程序处理数据时,它就会在内存中保留同一类别的不同版本。
我们可以通过多种方式解决这个问题
1.在windows系统的startup.bat或Linux系统的startup.sh中设置以下值。
`
set JAVA_OPTS=" -Xms1563m -Xmx1563m -XX:NewSize=1024m -XX:MaxNewSize=1024m -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:+DisableExplicitGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"
`
2.另一种方法是在windows系统的startup.bat或Linux系统的startup.sh中设置以下值。
set CATALINA\_OPTS=" -Xms1563m -Xmx1563m -XX:NewSize=1024m -XX:MaxNewSize=1024m -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:+DisableExplicitGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"
3.大多数与permgen问题有关的问题是与SUN JVM实现有关的,所以你可以将JVM改为JRocket JVM以避免这类错误。
大多数情况下,permgen问题都能通过上述方法得到解决。
但是,上述方法还是不能解决,是的,上述设置不能帮助我解决异常,在这种情况下。
你需要看一下日志。在日志中,我看到了下面的信息:
SEVERE: A web application registered the JBDC driver [oracle.jdbc.driver.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
是的,这就是这个问题的罪魁祸首。我的应用程序在停止服务器后没有正确地取消注册,所以引用没有被清理并在内存中可用,这将是classloader的内存泄漏,再次启动后,classloader没有正确加载,引用存在于内存中。
解决这个问题的方法是将相应的oracle jar复制到tomcat/lib文件夹,以便从tomcat classloader中加载。