在使用Lucene索引文档时,我的JVM(1.6.0_29)在密集使用时不断崩溃。 我明白了:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00002b6b196d767c, pid=26417, tid=1183217984
#
# JRE version: 6.0_29-b11
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.4-b02 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# J org.apache.lucene.store.DataInput.readVInt()I
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
环境:
JDK:1.6u29(与1.6_02同样的问题) Lucene版本3.4.0
vm_info:适用于linux-amd64 JRE(1.6.0_29-b11)的Java HotSpot(TM)64位服务器VM(20.4-b02),构建于2011年10月3日01:19:20“java_re”与gcc 3.2 .2(SuSE Linux)
操作系统:CentOS 5.0版(最终版)
jvm_args:-Dcatalina.home = / var / local / tomcat-8081 -Dcatalina.base = / var / local / tomcat-8081 -Djava.io.tmpdir = / var / tmp -Dfile.encoding = UTF-8 -Xmx1024M -XX:MaxPermSize = 96m
这似乎是在jdk 1.7中修复的jdk问题,但引入了其他问题。 https://issues.apache.org/jira/browse/LUCENE-3335 “Java 7包含自1.6.0_21以来对readVInt问题的修复(约,LUCENE-2975)”
那么,如何使用JDK 1.6修复此问题? 我应该升级到jdk 1.7吗?
答案 0 :(得分:4)
这些JDK问题也在1.6.9_29(不仅仅是1.7.0u1)中得到修复。 ReadVInt不再崩溃。因此,您的崩溃与任何着名的java6 / 7错误无关。 (vint bug不会让你的JVM崩溃,只会通过返回错误的值来破坏你的索引 - 而且这个版本自Lucene 3.1以来肯定是固定的。)
但是你可能会崩溃你的JVM:你是64位平台(Linux),因此默认目录实现是MMapDirectory。 Lucene使用hack能够从虚拟地址空间取消映射映射文件。 JVM本身不允许这样做,但是取消依赖垃圾收集器,这对Lucene来说是一个问题。默认情况下,MMapDirectory在关闭IndexInputs后取消映射文件。 MMapDirectory根本没有同步,所以当另一个线程在取消映射后尝试访问IndexInput时,它将访问一个未映射的地址并且将是SIGSEGV。
如果您的代码是正确的,这不会发生,但看起来您正在使用已经关闭的IndexReader / IndexWriter来访问索引。在Lucene 3.5(即将推出)之前,丢失的IndexReader中的检查将使已经关闭的IndexReader及其所有已关闭(和未映射)的IndexInputs尝试访问索引数据和段错误成为可能。
在3.5中,我们添加了额外的安全检查以防止此非法访问,但它不是100%(因为缺少同步)。我会检查代码并检查没有任何内容访问封闭索引。
检查这是否是您的问题的简单检查是使用NIOFSDirectory(在Linux上较慢)而不是MMapDirectory。如果它没有崩溃并且可能抛出AlreadyClosedExceptions,则该错误正在访问已关闭的索引。
答案 1 :(得分:0)
根据this article,以下内容也可能在Java 6中引起它:
请注意:如果Java 6用户使用其中一个,则会受到影响 JVM选项,默认情况下未启用: -XX:+ OptimizeStringConcat或 -XX:+ AggressiveOpts
您使用其中任何一种吗?