Подтвердить что ты не робот

Java JRE фатальная ошибка: слишком много умножений

Я пытался проверить скорость Math.pow() на умножение "вручную" и наткнулся на эту ошибку:

В Java Runtime Environment обнаружена фатальная ошибка:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) при pc = 0x000000005ac46888, pid = 1508, tid = 6016

Версия JRE: среда выполнения Java (TM) SE (8.0_25-b18) (сборка 1.8.0_25-b18)
Java VM: Java HotSpot (TM) 64-разрядная серверная VM (25.25-b02 смешанный режим windows-amd64 сжатые oops)
Проблемная рамка:
V [jvm.dll + 0x496888]

Не удалось записать основной дамп. Minidumps по умолчанию не включены в клиентских версиях Windows

Код, генерирующий его:

long t = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
    double val = i*i*i*i*i /* 256 times *i */ *i*i*i;
    sum ^= Double.doubleToLongBits(val);
}
System.out.println((System.nanoTime() - t) / 10000000);

Я понимаю, что это действительно экстремальный случай, но все же, это правильный код, и самое худшее, что может случиться, должно быть связано с Inf в значении, а не с JRE. Это действительно стандартное поведение, описанное oracle, или просто ошибка, которую никто не хочет исправлять, потому что, если вы ее видите, вы действительно плохой человек.

Для записи с NetBeans 8.0.2

ОБНОВЛЕНИЕ 1

Кажется, проблема в величине умноженного числа.

long t = System.nanoTime();
for(int j = 0; j < 10000000; j++) {
    int i = j % 50;
    double val = i*i*i*i*i /* 256 times *i */ *i*i*i;
    sum ^= Double.doubleToLongBits(val);
}
System.out.println((System.nanoTime() - t) / 10000000);

будет просто отлично.

ОБНОВЛЕНИЕ 2

Пытался запустить его с консоли с помощью

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

и прошел просто отлично, поэтому я предполагаю, что это должно быть либо проблема с этим конкретным JRE, либо с NetBeans.

4b9b3361

Ответ 1

Это определенно похоже на ошибку JVM для меня. Это более подходит как отчет об ошибке, чем вопрос о SO. См. http://bugreport.java.com/

Ответ 2

Это отлично работает для меня. Где проблема для вас? Изолируйте проблему, уменьшая количество умножений или количество циклов. Работает ли он с 50 умножениями?

long sum=0;
long t = System.nanoTime();
for (int i = 1; i < 10000000; i++) {
    double val = i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i
                    *i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i
                    *i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i*i; 
            // set of 10 *i*i*i*i*i*i*i*i*i*i
    sum ^= Double.doubleToLongBits(val);
}
System.out.println(sum);
System.out.println((System.nanoTime() - t) / 10000000);

jre1.8.0_51

Выход:   

    -32067153335156736
    614

Даже умножение на еще 10 итераций работает, но очень медленно. время 6020

Ответ 3

Попробуйте использовать BigInteger.

import java.math.BigInteger;

public class hackerrank {
    public static void main (String args[]){
        BigInteger x = new BigInteger("10000000");
        BigInteger sum = BigInteger.ZERO;
        long t = System.nanoTime();
        for (BigInteger i = BigInteger.ONE; i.compareTo(x) == -1; i = i.add(BigInteger.ONE)) {
            BigInteger j = i.remainder(new BigInteger("50"));
            BigInteger val = j.pow(256);
            sum = sum.xor(val);
        }
        System.out.println((System.nanoTime() - t) / 10000000);
    }
}

Выход: 4083