关于 Unloading class sun.reflect.GeneratedSerial...
http://my.oschina.net/linuxfelix/blog/133277
最近,由于項目需要,要在一個Tomcat上部署多個Web應用。考慮到Tomcat的最大堆大小為128MB,所以我對Tomcat的JVM參數做以下調整,并輸出GC日志。參數如下
?
view source print?| 1 | -Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=512M -Xloggc:D:/TomcatGc.log |
?
然而在應用啟動完成之后,在控制臺不斷輸出以下“奇怪信息”
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日志,發現JVM從394.237S到2040.453s之間都在頻繁地進行FullGC
?
要知道JVM頻繁地進行FullGC肯定不是什么好事情。于是就通過Google去搜索是什么原因導致那些“奇怪信息”的輸出。
網上有許多回答都說是由于堆空間不夠,JVM正嘗試回收一些無用的對象。我在StackOverFlow上也發起相關的提問,給的回答也是這個 。所以就信以為真,開始加大堆大小,調整參數如下:
view source print?| 1 | -Xms512m -Xmx1024m -XX:PermSize=128M? -XX:MaxPermSize=512M -Xloggc:D:/TomcatGc.log |
在應用啟動完成之后,一開始并沒有立即出現那些“奇怪信息”。但是在大約過了10分鐘左右。控制臺又不斷輸出上述“奇怪信息”。
經過一番折騰之后,我終于否決了堆空間不夠導致那些”奇怪信息“輸出的回答了,這哪里是這個原因導致的,簡直就是坑爹。
那到底是什么原因導致的呢?回想起自己以前學過的JVM的知識。JVM運行時數據區域有分為方法區和堆。方法區(也叫永久代)用于存儲類型信息、常量和靜態變量等。堆空間用于存儲對象和數組等。根據GC算法,堆空間又分為新生代和老年代。在新生代中會觸發MinorGC(也稱GC),老年代會觸發MajorGC(也稱Full GC).關于更多的信息可以參考我之前的文章
然而很多人都忽略了方法區也可以存在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.折騰一天算是浪費時間,但是從中也學到和鞏固不少知識也算是因禍得福。
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?
總結
以上是生活随笔為你收集整理的关于 Unloading class sun.reflect.GeneratedSerial...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: camel route 创建顺序
- 下一篇: Method.invoke 异常捕获