В делении двух int в Java нет ничего особенного. Если не обрабатывается один из двух особых случаев:
- Деление на ноль. (JVMS требует, чтобы виртуальная машина выдавала
ArithmeticException) - Переполнение деления (
Integer.MIN_VALUE / -1, JVMS требует, чтобы результат был равенInteger.MIN_VALUE) (Этот вопрос относится исключительно к этому случаю).
Из главы 6. Java Набор инструкций виртуальной машины. idiv:
Есть один частный случай, который не удовлетворяет этому правилу: если делимое является отрицательным целым числом наибольшей возможной величины для типа
int, а делитель равен-1, то происходит переполнение, и результат равен делимому. Несмотря на переполнение, в этом случае исключений не возникает.
На моем компе (x86_64) родное деление выдает ошибку SIGFPE.
Когда я компилирую следующий код C:
#include <limits.h>
#include <stdio.h>
int divide(int a, int b) {
int r = a / b;
printf("%d / %d = %d\n", a, b, a / b);
return r;
}
int main() {
divide(INT_MIN, -1);
return 0;
}
Я получаю результат (на x86):
tmp $ gcc division.c
tmp $ ./a.out
Floating point exception (core dumped)
Точно такой же код, скомпилированный на ARM (aarch64), выдает:
-2147483648 / -1 = -2147483648
Таким образом, кажется, что на x86 виртуальная машина Hotspot должна выполнять дополнительную работу, чтобы справиться с этим случаем.
- Что в этом случае делает виртуальная машина, чтобы не сильно терять производительность в скомпилированном коде?
- Использует ли он возможности обработки сигналов в системах POSIX? Если да, то что он использует в Windows?