JVM 在 Lucene DataInput.readVInt 上崩溃
当使用 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),由“java_re”于 2011 年 10 月 3 日 01:19:20 构建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 问题,已在 jdk 1.7 中修复,但其他问题在介绍了。 https://issues.apache.org/jira/browse/LUCENE-3335 “自 1.6.0_21 起,Java 7 包含对 readVInt 问题的修复(大约,LUCENE-2975)”
那么,如何使用 JDK 1.6 修复此问题? 我应该升级到jdk 1.7吗?
My JVM (1.6.0_29) keeps crashing on intensive use when indexing documents with Lucene.
I get:
#
# 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
#
Environment:
JDK: 1.6u29 (same issue with 1.6_02)
Lucene Version 3.4.0
vm_info: Java HotSpot(TM) 64-Bit Server VM (20.4-b02) for linux-amd64 JRE (1.6.0_29-b11), built on Oct 3 2011 01:19:20 by "java_re" with gcc 3.2.2 (SuSE Linux)
OS:CentOS release 5.0 (Final)
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
It seems to be a jdk issue that was fixed in jdk 1.7, but other issues where introduced.
https://issues.apache.org/jira/browse/LUCENE-3335
"Java 7 contains a fix to the readVInt issue since 1.6.0_21 (approx, LUCENE-2975)"
So, how can I fix this issue using JDK 1.6?
Should I upgrade to jdk 1.7?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这些 JDK 问题也在 1.6.9_29 中得到了修复(不仅仅是 1.7.0u1)。 ReadVInt 不会再崩溃。因此,您的崩溃与任何“著名的 java6/7 bug”都无关(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,则错误正在访问关闭的索引。
these JDK issues are also fixed in 1.6.9_29 (not only 1.7.0u1). ReadVInt can no longer crash. So your crash is not related to any of the "famous java6/7 bugs" (the vint bug does not crash your JVM at all it just corrupts your index by returning wrong values - and this one is definitely fixed since Lucene 3.1).
But there is another chance you can crash your JVM: You are on a 64 bit platform (Linux), so the default directory implementation is MMapDirectory. Lucene uses a hack to be able to unmap mapped files from virtual address space. This is not allowed by the JVM itsself, but makes unmapping dependent on garbage collector, which is a problem for Lucene. By default MMapDirectory unmaps the files after closing the IndexInputs. MMapDirectory is not synchronized at all, so when another thread tries to access the IndexInput after unmapping it will access an unmapped address and will SIGSEGV.
If your code would be correct this cannot happen, but it looks like you are using an already closed IndexReader/IndexWriter to access the index. Before Lucene 3.5 (will come out soon), missing checks in IndexReader will make it possible that an already closed IndexReader with all its closed (and unmapped) IndexInputs tries to access index data and segfaults.
In 3.5 we added additional safety checks to prevent this illegal access, but its not 100% (as synchronization is missing). I would review the code and check that nothing accesses closed index.
A simple check to see if this is your issue would be to use NIOFSDirectory (slower on Linux) instead of MMapDirectory. If it does not crash and possibly throws AlreadyClosedExceptions, the bug is accessing closed indexes.
根据这篇文章 以下情况也可能在 Java 6 中导致该问题:
您使用其中的任何一个吗?
According to this article the following could cause it in Java 6 as well:
Are you using any of them?