Lucene在索引数据比较少的时候内存问题不是很明显,但如果索引文件有几个G的时候,内存就会出现溢出问题.这个问题是由于Lucene的内部Bug引起的,如果在搜索时设置了排序,则它会缓存相关数据,但在下一次搜索时,它没有清除内部的一些缓存数据,所以会造成内存溢出.这个问题的解决办法就是改Lucene的源代码. 修改步骤如下: 1.修改Lucene源代码中Index目录中的IndexReader.cs文件,在其中加上如下代码: public string m_cacheKey = null; (这一行代码主要用于Lucene内部用缓存的键值),以后清除缓存就用这个键值. 2.修改Lucene源代码中Search目录中的IndexSearcher.cs文件,修改其中的Close方法代码如下: public override void Close() { //清除缓存数据 if (!string.IsNullOrEmpty(reader.m_cacheKey)) { if (null != FieldSortedHitQueue.Comparators) { FieldSortedHitQueue.Comparators.ReleaseCache(reader.m_cacheKey); } Lucene.Net.Search.FieldCache_Fields.DEFAULT.ReleaseFieldCache(reader.m_cacheKey); Lucene.Net.Search.ExtendedFieldCache_Fields.EXT_DEFAULT.ReleaseExtendedFieldCache(reader.m_cacheKey); // 立即回收垃圾 GC.Collect(); } //关闭读取器 if (closeReader) reader.Close(); } 3.修改Lucene源代码中Search目录中的FieldCache.cs文件,修改其中的接口public interface FieldCache,并添加接口方法,方法代码如下: //用于清除缓存 void ReleaseFieldCache(string strCacheKey); 4.修改Lucene源代码中Search目录中的FieldCacheImpl.cs文件,添加下列方法, 代码如下: //用于清除缓存 public void ReleaseFieldCache(string strCacheKey) { bytesCache.ReleaseCache(strCacheKey); shortsCache.ReleaseCache(strCacheKey); intsCache.ReleaseCache(strCacheKey); floatsCache.ReleaseCache(strCacheKey); stringsCache.ReleaseCache(strCacheKey); stringsIndexCache.ReleaseCache(strCacheKey); autoCache.ReleaseCache(strCacheKey); customCache.ReleaseCache(strCacheKey); } 修改内部类:internal abstract class Cache,添加方法如下: //用于清除缓存 public void ReleaseCache(string strCacheKey) { if (null != readerCache) { lock (readerCache.SyncRoot) { if (null != readerCache[strCacheKey]) { ((System.Collections.Hashtable)readerCache[strCacheKey]).Clear(); } } } } 修改方法Get: public virtual System.Object Get(IndexReader reader, System.Object key) { System.Collections.IDictionary innerCache; System.Object value_Renamed; lock (readerCache.SyncRoot) { //改键值为静态值 innerCache = (System.Collections.IDictionary)readerCache[reader.m_cacheKey]; //innerCache = (System.Collections.IDictionary) readerCache[reader]; if (innerCache == null) { innerCache = new System.Collections.Hashtable(); //改键值为静态值 readerCache[reader.m_cacheKey] = innerCache; //readerCache[reader] = innerCache; value_Renamed = null; } else { value_Renamed = innerCache[key]; } if (value_Renamed == null) { value_Renamed = new CreationPlaceholder(); innerCache[key] = value_Renamed; } } if (value_Renamed is CreationPlaceholder) { lock (value_Renamed) { CreationPlaceholder progress = (CreationPlaceholder) value_Renamed; if (progress.value_Renamed == null) { progress.value_Renamed = CreateValue(reader, key); lock (readerCache.SyncRoot) { innerCache[key] = progress.value_Renamed; } } return progress.value_Renamed; } } return value_Renamed; } 5.修改Lucene源代码中Search目录中的ExtendedFieldCache.cs文件,修改其中的接口public interface ExtendedFieldCache : FieldCache,并添加接口方法,方法代码如下: //用于清除缓存 void ReleaseExtendedFieldCache(string strCacheKey); 6.修改Lucene源代码中Search目录中的ExtendedFieldCacheImpl.cs文件,添加下列方法,代码如下: //用于清除缓存 public void ReleaseExtendedFieldCache(string strCacheKey) { longsCache.ReleaseCache(strCacheKey); doublesCache.ReleaseCache(strCacheKey); autoCache.ReleaseCache(strCacheKey); } 通过上述6个步骤,内存溢出问题就可以解决了,但还有一个需要注意的就是在更新索引时,一定要调用如下代码,才能清掉缓存: //清缓排序缓存数据IndexSearcher.Close(); IndexReader.Close();