java深度-----GC

[code]
垃圾收集的实现:
1。引用计数:一个A对象,如果有程序使用了这个引用对象,那么引用计数加1,
当一个对象使用完毕之后引用计数减1,那么引用计数为0的时候,则可以回收
他不能识别循环引用

2。跟踪收集
如果A对象引用了B对象,那么虚拟机会记住这个引用路径,同时B对象引用了C对象,那么也会记录这个路径
如果一个对象没有在路径图中,那么可以收集
缺点:需要维护一张引用的全景图,增加了内存开销,和图的遍历开销


3.基于对象跟踪的分代增量收集
基于对象跟踪---说明是由跟踪收集发展而来的,分代是指对堆进行了合理的划分
增量收集:不是每一次全部收集,而是累积的增量收集

Sun的JVM将整个堆分为三代:YoungGen,OldGen和PermGen(持久区),对YoungGen GC
是相对高效和快速的,YoungGen中,经历了若干次的 GC依然存活的对象(说明这些对象使用频率高,
不应该马上回收,所以让他们养老而不是直接干掉),"晋升"到OldGen.内存占用较大的对象,
则直接分配到OldGen(因为这种中型对象肯定不会被马上回收,会占用一定得生存时间,比如一
个数据库连接,我们需要对他进行缓存,需要反复利用,不会马上回收,所以重型对象放到老年
区可以使得他回收更慢),而PermGen 中用于存放长时间存活的对象,如 Class对象基础数据信息,
以及全局应用配置信息

Eden survivor spaces virtual



-------------Young-----------------
最开始一个对象会放到Young中的Eden,经过一定的时间会被复制到survivor spaces ,有些可能被复制到
年老区,被赋值剩余后的对象会被回收。

细致分析:
年轻区被进一步分为一个Eden区和两个Survior Space,而两个Suriveor Space
在同一时刻,总有一个是空的,这个空的Survivor Space被称为To Space,另外一个则被称为
From Space,在年轻区进行GC时,Eden中存活的对象会被copy到To Space中(大对象直接被拷贝到OldGen),
From Space 中尚不够Old资格的对象也被copy到To Space中,而剩余的则"晋升"到OldGen中。当To Space不足时,
那么本该被拷贝到To Space中的对象则被Tenured(拷贝到了年老对象当中)。。。。这里会带来性能问题哈--因为年老对象
会被认为是不应该轻易回收的,所以考量他回收的条件相对复杂得多,所以对年老对象的回收比对年轻对象的回收耗资源得多,
他甚至会挂起你的应用来收集资源,超卡。。。。。SUN JVM提供了调节Surivor Space大小的参数,当GCLog中出现Tenured字
样时,就可能是Surivor Space不够大造成的。
当年老区没有足够的空间,无法接纳由年轻晋升来的对象,那么YoungGen Collection Algorithm(年轻区算法)将会停止,
整个GC将会进行年老区域算法(因为JVM会认为,年轻区中这时也存在年老对象,当然需要使用年老算法啦)--术语:叫做
"全收集",对于OldGen不能只看其人有空闲就认为其大小已经足够,因为很可能一次年轻区的拷贝就可能触发全收集
小收集:当分配器不能满足分配请求时,先触发一个小收集,他只收集年轻区,因为年轻区的许多对象已经死亡,复制收集器
完全不用分析死亡原因,所以小收集快,高效

下面是阿里的邮件:
Dear all:
最近在测试环境经常出现应用的jboss进程在运行了一段时间后crash的情况,在应用的jboss日志中出现以下出错信息:
# JRE version: 6.0_18-b07
# Java VM: Java HotSpot(TM) 64-Bit Server VM (16.0-b13 mixed mode linux-amd64 )
# Problematic frame:
# V [libjvm.so+0x6227df]
#
# An error report file with more information is saved as:
# /home/6080/work/intl-myaliexpress/deploy/hs_err_pid29858.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
到底是什么原因导致以上情况的发生呢?那我们就需要查看具体的hs_err_pid29858.log日志文件来找答案了。
 在该文件的第17行有以下信息:
Current thread (0x00000000542e5800): GCTaskThread [stack: 0x00000000415a1000,0x00000000416a2000] [id=29861]
说明jvm在crash时,执行的是线程是GCTaskThread。
 我们再来看具体出了什么问题,在文件的第251——261行有以下内容:
=>0x00000000542e5800 (exited) GCTaskThread [stack: 0x00000000415a1000,0x00000000416a2000] [id=29861]
VM state:at safepoint (normal execution)
VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event])
[0x00000000542cddf0] Threads_lock - owner thread: 0x0000000054334800
[0x00000000542ce2f0] Heap_lock - owner thread: 0x00002aab00003000
Heap
PSYoungGen total 349120K, used 348912K [0x00002aaae46d0000, 0x00002aaaf9c20000, 0x00002aaaf9c20000)
eden space 348672K, 100% used [0x00002aaae46d0000,0x00002aaaf9b50000,0x00002aaaf9b50000)
从上面的日志可以肯定是Young GC的时候发生了异常,导致JVM crash。
在询问了老董和伯虎后,发现这个是JDK1.6.0_18的已知bug,bug report地址:http://bugs.sun.com/view_bug.do?bug_id=6896647
其主要原因是card-marking performance optimization算法在实现的时候有瑕疵,在某些情况下会引起heap corruption。这个情况主要发生在新创建的大对象
和Eden space大小差不多,然后jvm做young GC的时候。
解决方案:在启动参数中增加-XX:-ReduceInitialCardMarks将性能优化策略关闭。


[/code]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值