IBM JDK(二)

来源:互联网 发布:织梦网站分类目录源码 编辑:程序博客网 时间:2024/05/17 23:54

本文于2006年6月2日发表在搜狐博客



Compaction phase

当清扫完毕以后,就开始执行compactionJavacompaction是相当复杂的。因为移动一个对象,必须修改他们所有的reference。而且如果一个reference是来自一个stack,并且我们不能确定它是否指向一个真实的object,可能它仅仅是一个float,那么这些object

就不能被移动。一个对象是否可以被移动设计到它的”dosed”位是被置位。同样pinned object,那些被JNI引用的对象,只有到Jni unnpined的时候才能被移动。Pinned object的可否移动的判断更加复杂。主要依赖于mptr低三位标示它是否被清扫掉。标示被清扫的的位存在两个地方:1. The size + flags字段,如果被标记到OLINK_IsSwapped. 2. mptr被标记到GC_FirstSwapped。因此看来Javaint这种普通类型和Object分开处理在GC中会造成过多的不能移动的对象和过多的碎片。对于GC来说很不明智,而且在其他地方也看不出有什么必要分开处理。

否则干吗还要做一个Integer类呢?而C#在这点上来说优势更大。

IBM java中的Compaction算法为了避免过多的移动对象和利用移动处理一些没有被收集的空闲块因而出奇的复杂。他采用了一种和hotspot不同的算法。Sam Borman举了一个很形象的例子,把整个Heap想象成一个仓库,仓库堆放了不同尺寸的家具。由于出库的原因,家具之间存在着一定的空隙。Compaction的工作就是把家具往一个方向推来清理空隙。把靠近墙的家具推倒墙边,然后让第二个家具与第一件紧靠在一起。以此类推,然后所有得家具靠再一起,而空隙在另外一边。Pinned and dosed objects 不能被移动的情况会复杂化这个算法,但是主要思想不变。

紧缩规避(Compaction avoidance)

Compaction avoidance的主要目的在于开辟较大内存的时候降低Compaction的使用次数来保证GC pause time能够足够短。在Ibm jvm中的Compaction的执行条件如下:

1.如果开辟一个大内存的时候遍例Free list发现没有合适的free storge激发alloc failure时间

2.在上次GC过程中出现了一次alloc failure

3.被激活的Heap(heap limitedheap base之间的heap)只有5%free

4.被激活的Heap不大于128K

IBM jvm在上面四个条件中满足一项就执行compaction。其中最为常见的是第一种,

为了避免CompanctionIbmjava采用了紧缩规避的方法。这个方法称为荒野内存(wilderness preservation),也就是在heap limit之上再开辟一块内存。这块内存保持原始状态,其大小为激活Heap5%,默认设置为3M.如果一旦有一个大块内存需要开辟,而freelist中没有合适的storge的时候就使用wilderness preservation保证不抛出 alloc failure。一旦wilderness被用尽则产生一个alloc failure通知GC执行Compaction。通常来说wilderness preservation能够保证不使用Compaction,因为基本上使用到wilderness的对象是这个应用程序中最大的对象。

IbmJVM关键实现就是这样,我们可以看到ibmJVM使用的很多算法让我们原本考虑的一些gc的困难降低到了一个可以忍受的限度,比如STWpause time,其实只涉及了sweepcompactionmark phase在程序运行的同时就完成了基本不影响程序的正常工作。而且由于使用了bitsweep,紧缩规避使得STW的时间大大降低,他们两个的工作量的总和不到Mark30%。而且在多对称处理器上又采用并行marksweep,可以近一部的提高GC效率。好了用了两个小时写这篇文章真的很累,我把JavaVM的实现细节公布出来,大家谈论就有的放肆了吧。我也是匆匆看了以后结合以前经验写出来得,大家看了以后有什么意见尽管提。我不能回答的,写信去问Sam borman

0 0
原创粉丝点击