垃圾回收是Java程序员了解最少的一部分。他们认为Java虚拟机接管了垃圾回收,所以不必去担忧内存的申请,分配等问题。可是随着应用愈来愈复杂,垃圾回收也愈来愈复杂,一旦垃圾回收变的复杂,应用的性能将会大打折扣。因此,Java程序员了解垃圾回收的机制而且知道怎样解决“内存溢出”问题会有很大的益处。在Java中,有两个很是广泛的内存溢出问题。一个是堆内存溢出,另外一个是持久代内存溢出。html
Java对象是java 类的实例。每当建立一个Java对象时,Java虚拟机都会建立该对象的内部引用而且保存在堆中。若是一个类是第一次访问,那么它必须经过Java虚拟机加载进来。类加载是定位,寻找,加载class文件和解析class文件结构的过程。类加载器负责确保加载正确的class文件。Java程序里面每个class文件须要被同一个类加载加载。类加载器是 java.lang.ClassLoader 类的实例。目前为止,类加载器是在持久代空间里面加载类的。java
Java虚拟机也建立了Java类的内部引用保存在持久代。在垃圾回收期间,Java对象和类都当作对象处理而且以一样的方式回收。最初Java对象和类都是保存在堆中。程序员
一个性能优化措施:一旦持久代建立后,就会把classes放入里面。Classes是Java虚拟机的部分实现,咱们不该该用咱们的数据结构填满Java堆。持久代包含如下类信息:apache
如今咱们知道了持久代是什么,接下来看看在这块会是什么缘由引发内存问题。数组
当Java虚拟机须要加载定义的一个新class,可是在持久代中没有足够的空间就会抛出‘Java.Lang.OutOfMemoryError: PermGen Space’异常。默认分配给持久代的大小在server模式下是64MB ,在client模式下是32MB 。这就有两个缘由可能会引发持久代内存溢出问题的发生。tomcat
第一个缘由多是你应用或者服务器已经有很是多的class在你的持久代中,已经不能容纳全部的class了。性能优化
若是是由于大量的class致使持久代的空间的不足引发的问题,那么你能够增长持久代的大小经过–XX:MaxPermSize=XXm 参数。这将增长持久代的可用空间来保存class。看起来像这样: -XX:MaxPermSize=256m服务器
这个参数表示在使用CMS垃圾回收机制的时候是否启用类卸载功能。默认这个是设置为不启用的,因此你想启用这个功能你须要在Java参数中明确的设置下面的参数:数据结构
-XX:+CMSClassUnloadingEnabled框架
若是你启用了CMSClassUnloadingEnabled ,垃圾回收会清理持久代,移除再也不使用的classes。这个参数只有在 UseConcMarkSweepGC 也启用的状况下才有用。参数以下:
-XX:+UseConcMarkSweepGC
这个参数表示是否会清理持久代。默认是不清理的,所以咱们须要明确设置这个参数来调试持久代内存溢出问题。这个参数在Java6中被移除了,所以你须要使用 -XX:+CMSClassUnloadingEnabled 若是你是使用Java6或者后面更高的版本。那么解决持久代内存大小问题的参数看起来会是下面这样子:
-XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC XX:+CMSClassUnloadingEnabled
第二个缘由多是内存泄露。那么加载的类怎样变成不用的呢?
在Java中一般class是永久存在的。一旦class被加载,他们就呆在内存中,即便服务器上的应用停掉了。像cglib这样能够动态产生class的类库会使用不少持久代空间,由于它动态的建立不少class。频繁的使用在运行时建立的代理类。当一个类定义能够为多个实例重用时很容易建立新的代理类。
Sping和Hibernate常常会代理某些class。这些代理的class是经过类加载器加载的。产生的类定义若是一直不回收就会致使持久代空间很快就满了。
你须要肯定是否是内存泄露引发的持久代空间的问题,同时解决它。增长持久代空间大小将不会有用,这只会延迟它的发生,由于在某个时间点持久代仍是会被填满。
若是你正在使用tomcat遇到了内存泄露问题,最新版本的tomcat有能力处理一些内存泄露问题。详细请看:
一旦你遇到了持久代内容溢出问题,你须要找出这个问题是由于加载了大量的class文件仍是内存泄露引发的。若是是由于class的数量过多,你能够增长持久代分配的空间大小来解决这个问题。若是是由于内存泄露,你须要引发内存泄露的根源所在而且定位它。一些框架像cglib,Spring,Hibernate会建立大量的动态类,所以对于使用这些框架的应用最好是分配多一点的持久代空间。
原文连接: http://www.javacodegeeks.com/2013/12/decoding-java-lang-outofmemoryerror-permgen-space.html