未添加本机代码的 Java 致命错误 SIGSEGV

Java fatal error SIGSEGV with no added native code(未添加本机代码的 Java 致命错误 SIGSEGV)
本文介绍了未添加本机代码的 Java 致命错误 SIGSEGV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我从 Java 编译器收到一条我不理解的错误消息.我已经使用 Java 6 和 7 在 OSX 10.6、10.9 和 Ubuntu 14.04 上测试了我的代码.当我使用 Eclipse 调试器或从解释器(使用 -Xint 选项)运行时,一切运行正常.否则,我会收到以下消息:

I am getting an error message from the Java compiler that I don't understand. I've tested my code on OSX 10.6, 10.9, and Ubuntu 14.04, with both Java 6 and 7. When I run with the Eclipse debugger or from the interpreter (using -Xint option), everything runs fine. Otherwise, I get the following messages:

Java 1.6:

Invalid memory access of location 0x8 rip=0x1024e9660

Java 1.7:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x000000010f7a8262, pid=20344, tid=18179
#
# JRE version: Java(TM) SE Runtime Environment (7.0_60-b19) (build 1.7.0_60-b19)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.60-b09 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.dylib+0x3a8262]  PhaseIdealLoop::idom_no_update(Node*) const+0x12
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

Java 7 有更多错误输出(保存到文件中),但不幸的是,我无法将其放入本文的字符数限制中.有时我需要运行我的代码几次才能出现错误,但它经常出现.

There's more error output for Java 7 (that is saved to a file) but unfortunately I can't fit it in the character limit of this post. Sometimes I need to run my code a couple of times for the error to come up, but it appears more often than not.

我的测试用例涉及以对数比例缓存一些计算.具体来说,给定 log(X),log(Y),...,我有一个计算 log(X+Y+...) 的小类.然后我将结果缓存在 HashMap 中.

My test case involves cacheing some computations in logarithmic scale. Specifically, given log(X),log(Y),..., I have a small class that computes log(X+Y+...). And then I cache the result in a HashMap.

奇怪的是,更改一些循环索引似乎使问题消失了.特别是,如果我替换

Strangely, changing some loop indices seems to make the problem go away. In particular, if I replace

for (int z = 1; z < x+1; z++) {
    double logSummand = Math.log(z + x + y);
    toReturn.addLogSummand(logSummand);
}

for (int z = 0; z < x; z++) {
    double logSummand = Math.log(1 + z + x + y);
    toReturn.addLogSummand(logSummand);
}

然后我没有收到错误消息并且程序运行正常.

then I don't get the error message and the program runs fine.

我的最小示例如下:

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestLogSum {
    public static void main(String[] args) {

        for (int i = 0; i < 6; i++) {
            for (int n = 2; n < 30; n++) {
                for (int j = 1; j <= n; j++) {
                    for (int k = 1; k <= j; k++) {
                        System.out.println(computeSum(k, j));                       
                    }
                }
            }
        }
    }

    private static Map<List<Integer>, Double> cache = new HashMap<List<Integer>, Double>();
    public static double computeSum(int x, int y) {     
        List<Integer> key = Arrays.asList(new Integer[] {x, y});

        if (!cache.containsKey(key)) {

            // explicitly creating/updating a double[] array, instead of using the LogSumArray wrapper object, will prevent the error
            LogSumArray toReturn = new LogSumArray(x);

            // changing loop indices will prevent the error
            // in particular, for(z=0; z<x-1; z++), and then using z+1 in place of z, will not produce error
//          for (int z = 0; z < x; z++) {
//              double logSummand = Math.log(1 + z + x + y);
            for (int z = 1; z < x+1; z++) {
                double logSummand = Math.log(z + x + y);
                toReturn.addLogSummand(logSummand);
            }

            // returning the value here without cacheing it will prevent the segfault
            cache.put(key, toReturn.retrieveLogSum());
        }
        return cache.get(key);
    }

    /*
     * Given a bunch of logarithms log(X),log(Y),log(Z),...
     * This class is used to compute the log of the sum, log(X+Y+Z+...)
     */
    private static class LogSumArray {      
        private double[] logSummandArray;
        private int currSize;

        private double maxLogSummand;

        public LogSumArray(int maxEntries) {
            this.logSummandArray = new double[maxEntries];

            this.currSize = 0;
            this.maxLogSummand = Double.NEGATIVE_INFINITY;
        }

        public void addLogSummand(double logSummand) {
            logSummandArray[currSize] = logSummand;
            currSize++;
            // removing this line will prevent the error
            maxLogSummand = Math.max(maxLogSummand, logSummand);
        }

        public double retrieveLogSum() {
            if (maxLogSummand == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;

            assert currSize <= logSummandArray.length;

            double factorSum = 0;
            for (int i = 0; i < currSize; i++) {
                factorSum += Math.exp(logSummandArray[i] - maxLogSummand);
            }

            return Math.log(factorSum) + maxLogSummand;
        }
    }
}

推荐答案

所以看了评论,好像这是JVM中的一个bug,需要报告给Oracle.因此,我继续向 Oracle 提交了错误报告.当我收到他们的回复时,我会发布更新.

So after reading the comments, it seems like this is a bug in the JVM that needs to be reported to Oracle. So, I have gone ahead and filed a bug report to Oracle. I'll post updates when I hear back from them.

感谢所有尝试过代码并发现它在您的机器上也出现问题的人.

Thanks to all those who tried the code and found it breaks on your machines as well.

如果有人有能力/倾向于找出编译器中的哪些代码导致了这个错误,那么听到它会很棒:)

If there is anyone with the ability/inclination to figure out what code in the compiler is causing this error, it would be awesome to hear about it :)

更新: Oracle 的某个人昨天回复了,他说他准备了修复该错误的方法,并要求将我的代码作为回归测试 :) 他没有解释问题是什么,除了说它在 HotSpot JIT 中,但他确实向我发送了他所做更改的链接,以防有人感兴趣:http://cr.openjdk.java.net/~kvn/8046516/webrev/

UPDATE: Someone from Oracle responded yesterday, he said he prepared a fix for the bug and also asked to include my code as a regression test :) He didn't explain what the problem was, beyond saying it was in the HotSpot JIT, but he did send me a link with the changes he made, in case anyone is interested: http://cr.openjdk.java.net/~kvn/8046516/webrev/

这篇关于未添加本机代码的 Java 致命错误 SIGSEGV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

How to send data to COM PORT using JAVA?(如何使用 JAVA 向 COM PORT 发送数据?)
How to make a report page direction to change to quot;rtlquot;?(如何使报表页面方向更改为“rtl?)
Use cyrillic .properties file in eclipse project(在 Eclipse 项目中使用西里尔文 .properties 文件)
Is there any way to detect an RTL language in Java?(有没有办法在 Java 中检测 RTL 语言?)
How to load resource bundle messages from DB in Java?(如何在 Java 中从 DB 加载资源包消息?)
How do I change the default locale settings in Java to make them consistent?(如何更改 Java 中的默认语言环境设置以使其保持一致?)