Java7“Solr / Lucene”错误有多严重?

显然,Java7在循环优化方面有一些令人讨厌的bug: Googlesearch 。

从报告和错误描述,我发现很难判断这个错误是多么重要(除非你使用Solr或Lucene)。

我想知道的是:

  • 我的(任何)程序受到影响的可能性有多大?
  • 这个bug是否足够确定,正常的testing会抓住它?

注意:我不能让我的程序的用户使用-XX:-UseLoopPredicate来避免这个问题。

任何热点错误的问题是,在获得你之前,你需要达到编译阈值(比如10000):所以如果你的unit testing是“微不足道的”,你可能不会理解它。

例如,我们在lucene中捕获了不正确的结果问题,因为这个特定的testing会创build20,000个文档索引。

在我们的testing中,我们随机化了不同的接口(例如不同的目录实现)和索引参数等等,testing只失败了1%的时间,当然它随后可以用相同的随机种子重现。 我们还对每个testing创build的索引运行checkindex,它们会进行一些理智的testing,以确保索引没有损坏。

对于我们发现的testing,如果你有一个特定的configuration:例如RAMDirectory + PulsingCodec +有效载荷存储在字段中,那么在达到编译阈值后,枚举循环遍历过帐返回不正确的计算,在这种情况下返回的文档一个术语!=为该术语存储的docFreq。

我们有很多的压力testing,重要的是要注意在这个testing中正常的断言实际上是通过的,其结尾的checkindex部分是失败的。

与此相关的一个大问题是lucene的增量索引从根本上将多个片段合并为一个片段:因此,如果这些枚举计算出无效数据,则将这个无效数据存储到新合并的索引中:又名腐败。

我会说这个bug比我们之前的循环优化器热点bug(比如翻牌的东西, https ://issues.apache.org/jira/browse/LUCENE-2975)要容易得多。 在这种情况下,我们得到了古怪的负面文档变化,这使得它很容易被捕获。 我们也只需手动展开一个方法来躲避它。 另一方面,我们最初的唯一“testing”是一个巨大的10GB的http://www.pangaea.de/索引,所以把它缩小到这个bug是很痛苦的。;

在这种情况下,我花了很多时间(例如上周的每个晚上)尝试手动展开/内联各种东西,尝试创build一些解决方法,以便避开错误并且不会创build损坏的索引。 我可以躲避一些案件,但是还有很多案件我不能……而且我敢肯定,如果我们能够在我们的testing中触发这些东西,那么还有更多的案例。

简单的方法来重现错误。 打开日食(靛蓝在我的情况),并转到帮助/search。 input一个searchstring,你会注意到eclipse崩溃。 看看日志。

 # Problematic frame: # J org.apache.lucene.analysis.PorterStemmer.stem([CII)Z # # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows # # If you would like to submit a bug report, please visit: # http://bugreport.sun.com/bugreport/crash.jsp # --------------- THREAD --------------- Current thread (0x0000000007b79000): JavaThread "Worker-46" [_thread_in_Java, id=264, stack(0x000000000f380000,0x000000000f480000)] siginfo: ExceptionCode=0xc0000005, reading address 0x00000002f62bd80e Registers: 

这个问题在2012年12月2日还存在于Oracle JDK的java -version java版本“1.7.0_09”中。Java(TM)SE运行时环境(build 1.7.0_09-b05)Java HotSpot(TM)64位服务器VM (build 23.5-b02,混合模式)和openjdk java版本“1.7.0_09-icedtea”OpenJDK Runtime Environment(fedora-2.3.3.fc17.1-x86_64)OpenJDK 64位服务器虚拟机(build 23.2-b09,混合模式)

奇怪的是,单独的任何-XX:-UseLoopPredicate或-XX:LoopUnrollLimit = 1选项可以防止错误发生,但是当一起使用时 – JDK失败,请参阅https://bugzilla.redhat.com/show_bug.cgi?id=849279

那么两年后,我相信OSX上的1.7.0_25-b15版本仍然存在这个错误(或其变种)。

通过非常痛苦的试验和错误,我确定使用Java 1.7与Solr 3.6.2和autocommit <maxTime>30000</maxTime>似乎会导致索引损坏。 它似乎只发生w / 1.7和maxTime在30000 – 如果我切换到Java 1.6,我没有任何问题。 如果我把maxTime降到3000,我没有问题。

JVM不会崩溃,但是它会导致RSolr死于Ruby中的以下堆栈跟踪: https ://gist.github.com/armhold/6354416。 在保存了几百条logging之后,它可以可靠地做到

考虑到这里涉及的许多层(Ruby,Sunspot,Rsolr等),我不确定我可以将其归结为明确certificateJVM错误的东西,但确实感觉这就是这里发生的事情。 FWIW我也试过了JDK 1.7.0_04,也出现这个问题。

据我所知,这个错误只能在服务器jvm中find。 如果你在客户端jvm上运行你的程序,你就清楚了。 如果你在jvm服务器上运行你的程序,这取决于程序问题的严重程度。