关于OutOfMemoryError的问题:tomcat中的PermGen空间和解决方案

107 阅读2分钟

最近,当我在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中加载。