天天看點

導緻Lucene無法索引查詢的NoClassDefFoundError

Lucene乃是當今免費開源搜尋引擎的霸主,确實它十分好用,發展勢頭也很生猛,在Apache組織的支援下不斷的更新、推出新版本。

但是其存在一個隐藏的很深的bug,相信困擾了不少和我一樣研究使用過它的人,這個bug從早期的版本到目前的V2.3.1一個存在,不能不說是一個遺憾。

具體觸發這個bug的原因很複雜,在某些環境、伺服器、應用中……

表現為建立索引檔案和執行查詢時報“NoClassDefFoundError”,跟進代碼會發現是“SegmentReader”這個類型不能建立執行個體,但怎麼看這個類都是存在的。其實問題在這(SegmentReader.java):

  /** *//** The class which implements SegmentReader. */

  private static Class IMPL;

  static ...{

    try ...{

      String name =

        System.getProperty("org.apache.lucene.SegmentReader.class",

                           SegmentReader.class.getName());

      IMPL = Class.forName(name);

    } catch (ClassNotFoundException e) ...{

      throw new RuntimeException("cannot load SegmentReader class: " + e, e);

    } catch (SecurityException se) ...{

      try ...{

        IMPL = Class.forName(SegmentReader.class.getName());

      } catch (ClassNotFoundException e) ...{

        throw new RuntimeException("cannot load default SegmentReader class: " + e, e);

      }

    }

  }

看到這句沒有“System.getProperty("org.apache.lucene.SegmentReader.class", SegmentReader.class.getName());”,鬼知道它什麼時候把這個系統屬性設入記憶體中的!它的本意是想動态加載SegmentReader,但反而有可能弄巧成拙,導緻Class.forName報出NoClassDefFoundError,更要命的是在static{}代碼段中的Error不會明确的顯示在異常堆棧中,任你用什麼debug手段都不能立即定位問題。

知道了問題,最簡單的解決方法,很直接,改代碼。把那個IMPL和static{}段幹脆去掉,不利用系統屬性動态加載就是了,就直接使用SegmentReader,就認準它了:-)

     本文轉自胡奇 51CTO部落格,原文連結:http://blog.51cto.com/huqicto/280972,如需轉載請自行聯系原作者