CachePolicy在JDBM有两种现成的实现,一个是MRU(Most Recently Used),另一个是SoftCache。
MRU用Hashtable来保存缓存对象,每一个对象都维护它的next和previous对象,这样形成一个双向链表。之所以采用Hashtable,应该是考虑同步的问题。

MRU的原则就是最多使用的缓存对象放在链表的最末尾,最少使用的缓存对象放在链表的头部。新加的缓存对象都是放在尾部,如果有size的限制,那么头部的缓存对象会随找size的限制会被purge,这样可以加入新的缓存对象。每次purge的时候都会调用注册的Listeners,如果抛出异常则这个缓存对象不会被删除。 

        CachePolicyListener listener;
        for (int i=0; i<listeners.size(); i++) {
            listener = (CachePolicyListener)listeners.elementAt(i);
            listener.cacheObjectEvicted(entry.getValue());
        }
注意传入到cacheObjectEvicted中的变量是一个value,即处理的是缓存的对象而不是缓存项(CacheEntry)。

SoftCache利用了java的一个类SoftReference(详见内存优化的两个参数SoftReference和WeakReference)。它维护了两个map,一个是MRU对象_internal,另一个是Map对象_cacheMap,用于缓存SoftReference。

put方法中有:_cacheMap.put(key, new Entry(key, value, _clearQueue));
Entry类如下:

private static class Entry extends SoftReference {
        private final Object _key;

        /**
         * Constructor that uses <code>value</code> as the soft
         * reference's referent.
         */
        public Entry(Object key, Object value, ReferenceQueue queue) {
            super(value, queue);
            _key = key;
        }

        /**
         * Gets the key
         * @return the key associated with this value.
         */
        final Object getKey() {
            return _key;
        }

        /**
         * Gets the value
         * @return the value; null if it is no longer accessible
         */
        final Object getValue() {
            return this.get();
        }
    }


get方法:

public Object get(Object key) {
        // first try the internal cache.
        Object value = _internal.get(key);
        if (value != null) {
            return value;
        }
        // poll and remove cleared references.
        removeClearedEntries();
        Entry entry = (Entry)_cacheMap.get(key);
        if (entry == null) { // object is not in cache.
            return null;
        }
        value = entry.getValue();
        if (value == null) { // object was in cache, but it was cleared.
            return null;
        }
        // we have the object. so we try to re-insert it into internal cache
        try {
            _internal.put(key, value);
        } catch (CacheEvictionException e) {
            // if the internal cache causes a fuss, we kick the object out.
            _cacheMap.remove(key);
            return null;
        }
        return value;
    }

MRU的使用具体可以看CacheRecordManager类,它的创建在Provider类中:
            RecordManager recman = new BaseRecordManager( name );
            MRU cache = new MRU( cacheSize );
            recman = new CacheRecordManager( recman, cache );

如果使用Factory获取RecordMagener
RecordManagerFactory.createRecordManager( String name,  Properties options ),
得到的就是CacheRecordManager,如果非得使用BaseRecordManager:
RecordManager recman = new BaseRecordManager( name );
直接new一个即可。