JVM配置
-server
-Xmx1024m
-Xms1024m
-XX:NewSize=256m
-XX:MaxNewSize=256m
-XX:PermSize=128m
-XX:MaxPermSize=128m
-XX:SurvivorRatio=8
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=5
-XX:CMSInitiatingOccupancyFraction=60
-XX:CMSMaxAbortablePrecleanTime=5
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxGCPauseMillis=1500
此,你有两条路可以走
1、继续使用jdk的dynamicproxy,但不要禁止class卸载。
2、使用cglibproxy,复用代理类,避免大量生成的代理类。
加上-noclassgc,可使jvm不卸载加载的class
from:
http://my.oschina.net/linuxfelix/blog/133277
然而很多人都忽略了方法区也可以存在GC操作。这次悲剧的产生也是由于自己开始忽略这点导致的。要知道方法区的GC主要回收两部分内容:废弃常量和无用的类(注意这里的类和对象是两个不同的概念)。
判断一个类是否是无用的类需要满足下面3个条件:
1.该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例
2.加载该类的ClassLoader已经被回收
3.该类对应的Java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
JVM可以对满足上述3个条件的无用类进行回收,这里说的仅仅是“可以”,而不是和对象一样,不使用了就必然会回收。是否对类进行回收,JVM提供了-Xnoclassgc参数进行控制。于是,我在Tomcat的Jvm参数里加上 -Xnoclassgc并限制 -XX:PermSize=128M -XX:MaxPermSize=128M.重新启动Tomcat后,上述“奇怪信息”就不在出现了,并抛出了OutOfMemory PermGen space 异常。关于 OutOfMemory PermGen space 异常。这里也有一个非常有趣的讨论,大家可以看下。
总结:
在大量使用发射、动态代理、cglib等框架比如Spring、hibernate等,都需要虚拟机具备类卸载的功能,以保证方法区不会溢出。如果限制类卸载功能及限制 PermSize大小,相信方法区很快就会溢出。所以那些“奇怪信息”也属于正常的输出。另外也可以通过调大 PermSize的值已保证有足够的空间来装载这些类信息,这样,“奇怪信息”就可能不会输出了。
1.区分JVM的中永久代、新生代和老年代的概念。记住Full GC和GC都发生在堆中。
2.导致频繁的Full GC的原因是堆空间大小不够,但是奇怪的信息输出绝不是堆空间不足产生。
3.折腾一天算是浪费时间,但是从中也学到和巩固不少知识也算是因祸得福。