Java fatal error SIGSEGV
Erhalte ich eine Fehlermeldung aus der Java-compiler, dass ich nicht verstehe. Ich habe getestet, mein code auf OSX 10.6, 10.9 und Ubuntu 14.04, mit Java 6 und 7. Wenn ich mit dem Eclipse-debugger oder den interpreter (mit -Xint option), läuft alles einwandfrei. Andernfalls erhalte ich die folgenden Meldungen:
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
#
Es gibt noch mehr Fehler-Ausgabe für Java 7 (das ist in einer Datei gespeichert), aber leider kann ich nicht, es passt in die Zeichen-Grenze von diesem post.
Manchmal muss ich meinen code ein paar mal für den Fehler zu kommen, aber es scheint mehr als oft nicht.
Meinem test-Fall ist Cachen einige Berechnungen in logarithmischer Skala. Speziell, da log(X),log(Y),..., habe ich eine kleine Klasse berechnet, dass log(X+Y+...). Und dann habe ich cache das Ergebnis in einer HashMap.
Seltsam, ändert einige loop-Indizes scheint das problem Weg. Insbesondere, wenn ich ersetzen
for (int z = 1; z < x+1; z++) {
double logSummand = Math.log(z + x + y);
toReturn.addLogSummand(logSummand);
}
mit
for (int z = 0; z < x; z++) {
double logSummand = Math.log(1 + z + x + y);
toReturn.addLogSummand(logSummand);
}
dann bekomme ich keine Fehlermeldung und das Programm läuft wunderbar.
Mein minimal-Beispiel ist unter:
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;
}
}
}
InformationsquelleAutor der Frage jackkamm | 2014-06-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Also nach dem Lesen der Kommentare, es scheint, dies ist ein bug in der JVM zu vermelden, Oracle. Also, ich habe das durchgezogen und reichte einen bug-report zu Oracle. Ich werde updates posten, wenn ich wieder von Ihnen hören.
Danke an alle, die versucht haben den code gefunden und bricht es auf Ihrem Computer als auch.
Wenn es jemanden gibt, mit der Fähigkeit und Neigung, um herauszufinden, welchen code der compiler diesen Fehler verursacht, wäre es geil davon zu hören 🙂
UPDATE: Jemand von Oracle reagierte gestern, er sagte, er bereitete ein fix für den bug und gefragt, ob mein code als eine regression-test 🙂 Er musste nicht erklären, was das problem war, jenseits sagen, es war in der HotSpot JIT-Compiler, sondern er sandte mir einen link mit den änderungen die er gemacht, falls es jemanden interessiert: http://cr.openjdk.java.net/~kvn/8046516/webrev/
InformationsquelleAutor der Antwort jackkamm