【发布时间】:2020-08-10 04:08:10
【问题描述】:
在 Java 中划分两个 ints 并没有什么特别之处。除非处理了两种特殊情况之一:
- 除以零。 (JVMS要求虚拟机抛出
ArithmeticException) - 除法溢出(
Integer.MIN_VALUE / -1,JVMS 要求结果等于Integer.MIN_VALUE)(这个问题专门针对这种情况)。
来自Chapter 6. The Java Virtual Machine Instruction Set. 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 VM 似乎需要做额外的工作来处理这种情况。
- 在这种情况下,虚拟机如何在编译代码中不损失太多性能?
- 它是否利用了 POSIX 系统中的信号处理可能性?如果是这样,它在 Windows 上使用什么?
【问题讨论】:
标签: java jvm jvm-hotspot