关于 Unloading class sun.reflect.GeneratedSerial...
http://my.oschina.net/linuxfelix/blog/133277
最近,由于項(xiàng)目需要,要在一個(gè)Tomcat上部署多個(gè)Web應(yīng)用。考慮到Tomcat的最大堆大小為128MB,所以我對Tomcat的JVM參數(shù)做以下調(diào)整,并輸出GC日志。參數(shù)如下
?
view source print?| 1 | -Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=512M -Xloggc:D:/TomcatGc.log |
?
然而在應(yīng)用啟動(dòng)完成之后,在控制臺不斷輸出以下“奇怪信息”
view source print?| 1 | [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor339] |
| 2 | [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor336] |
| 3 | [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor341] |
| 4 | [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor342] |
| 5 | [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor340] |
?
查看輸出的GC日志,發(fā)現(xiàn)JVM從394.237S到2040.453s之間都在頻繁地進(jìn)行FullGC
?
要知道JVM頻繁地進(jìn)行FullGC肯定不是什么好事情。于是就通過Google去搜索是什么原因?qū)е履切?/span>奇怪信息”的輸出。
網(wǎng)上有許多回答都說是由于堆空間不夠,JVM正嘗試回收一些無用的對象。我在StackOverFlow上也發(fā)起相關(guān)的提問,給的回答也是這個(gè) 。所以就信以為真,開始加大堆大小,調(diào)整參數(shù)如下:
view source print?| 1 | -Xms512m -Xmx1024m -XX:PermSize=128M? -XX:MaxPermSize=512M -Xloggc:D:/TomcatGc.log |
在應(yīng)用啟動(dòng)完成之后,一開始并沒有立即出現(xiàn)那些“奇怪信息”。但是在大約過了10分鐘左右。控制臺又不斷輸出上述“奇怪信息”。
經(jīng)過一番折騰之后,我終于否決了堆空間不夠?qū)е履切?/span>奇怪信息“輸出的回答了,這哪里是這個(gè)原因?qū)е碌?#xff0c;簡直就是坑爹。
那到底是什么原因?qū)е碌哪?#xff1f;回想起自己以前學(xué)過的JVM的知識。JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域有分為方法區(qū)和堆。方法區(qū)(也叫永久代)用于存儲類型信息、常量和靜態(tài)變量等。堆空間用于存儲對象和數(shù)組等。根據(jù)GC算法,堆空間又分為新生代和老年代。在新生代中會觸發(fā)MinorGC(也稱GC),老年代會觸發(fā)MajorGC(也稱Full GC).關(guān)于更多的信息可以參考我之前的文章
然而很多人都忽略了方法區(qū)也可以存在GC操作。這次悲劇的產(chǎn)生也是由于自己開始忽略這點(diǎn)導(dǎo)致的。要知道方法區(qū)的GC主要回收兩部分內(nèi)容:廢棄常量和無用的類(注意這里的類和對象是兩個(gè)不同的概念)。
判斷一個(gè)類是否是無用的類需要滿足下面3個(gè)條件:
1.該類所有的實(shí)例都已經(jīng)被回收,也就是Java堆中不存在該類的任何實(shí)例
2.加載該類的ClassLoader已經(jīng)被回收
3.該類對應(yīng)的Java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法
JVM可以對滿足上述3個(gè)條件的無用類進(jìn)行回收,這里說的僅僅是“可以”,而不是和對象一樣,不使用了就必然會回收。是否對類進(jìn)行回收,JVM提供了-Xnoclassgc參數(shù)進(jìn)行控制。于是,我在Tomcat的Jvm參數(shù)里加上 -Xnoclassgc并限制 -XX:PermSize=128M ? -XX:MaxPermSize=128M.重新啟動(dòng)Tomcat后,上述“奇怪信息”就不在出現(xiàn)了,并拋出了OutOfMemory? PermGen space 異常。關(guān)于 OutOfMemory? PermGen space 異常。這里也有一個(gè)非常有趣的討論,大家可以看下。
總結(jié):
??? 在大量使用發(fā)射、動(dòng)態(tài)代理、cglib等框架比如Spring、hibernate等,都需要虛擬機(jī)具備類卸載的功能,以保證方法區(qū)不會溢出。如果限制類卸載功能及限制 PermSize大小,相信方法區(qū)很快就會溢出。所以那些“奇怪信息”也屬于正常的輸出。另外也可以通過調(diào)大 PermSize的值已保證有足夠的空間來裝載這些類信息,這樣,“奇怪信息”就可能不會輸出了。
1.區(qū)分JVM的中永久代、新生代和老年代的概念。記住Full GC和GC都發(fā)生在堆中。
2.導(dǎo)致頻繁的Full GC的原因是堆空間大小不夠,但是奇怪的信息輸出絕不是堆空間不足產(chǎn)生。
3.折騰一天算是浪費(fèi)時(shí)間,但是從中也學(xué)到和鞏固不少知識也算是因禍得福。
http://stackoverflow.com/questions/16708894/how-the-sun-reflect-generatedserializationconstructoraccessor-class-generated http://coding.derkeiler.com/Archive/Java/comp.lang.java.programmer/2006-11/msg00122.html?
總結(jié)
以上是生活随笔為你收集整理的关于 Unloading class sun.reflect.GeneratedSerial...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: camel route 创建顺序
- 下一篇: Method.invoke 异常捕获