Java如何处理除零?

时间:2014-01-21 21:27:43

标签: java divide-by-zero

是否只是在每次完成除法时检查除数是否与零不同(即使在JIT编码中)?

我的意思是VM如何在没有被操作系统杀死的情况下设法抛出异常?

4 个答案:

答案 0 :(得分:32)

在Unix环境中,signal通过SIGFPE引导除零,JVM将安装一个信号处理程序,用于捕获SIGFPE并依次throw 1}}是ArithmeticException。如果您对内部感兴趣,请参阅例如man signal

我认为OP所要求的是基于以下事实:除非SIGFPE处理程序到位,否则大多数进程将采取默认操作来接收此信号,即终止。因此,例如,一个C程序

 int main (int argc, char** argv) { int n = 5 / 0; } 

...如果它甚至编译,将被默认的SIGFPESIG_DFL操作杀死。相反,JVM的处理程序会发出(catchRuntimeException,以便可以以原生的方式处理这些异常。

正如其他几个人指出的那样,只是为了完整性,事实上从内核生成的SIGFPE通常是从处理器本身的特殊中断映射的;因此,“管道”就像

  • CPU错误陷阱中断→内核中断处理程序→SIGFPE SIG_DFL→处理死亡

  • CPU错误陷阱中断→内核中断处理程序→JVM中的SIGFPE处理程序→用户代码中的RuntimeException ArithmeticException

在非Unix平台上,处理类似。

答案 1 :(得分:7)

Java像任何其他语言一样处理这种情况。除以零错误会产生处理器异常,从而触发中断。操作系统“读取”中断,并在注册处理程序时将其转发给程序。由于Java注册了一个处理程序,它会收到错误,然后将其转换为在堆栈中向上移动的ArithmeticException

答案 2 :(得分:6)

JVM使用C:

像这样捕获除零
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

void fpe_handler(int signum) {
      printf("signal is %d", signum);
      printf("JVM throws an ArithmeticException here...\n");
      exit (1);
}

int main() {
      int a = 5;
      int b = 0;
      signal(SIGFPE, fpe_handler);   
      printf("%d\n", a / b); 
      return 0;
}

编译并运行它打印出来:

el@apollo:~$ gcc -o catch_sigfpe myc.c

el@apollo:~$ ./catch_sigfpe
signal is 8
JVM throws an ArithmeticException here...

el@apollo:~$

操作系统同步引发SIGFPE异常,C程序捕获它,然后java构造并向您提供ArithmeticException并自行清理以停止Java程序。

详细了解此处返回的信号:http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/index.jsp?topic=%2Fcom.ibm.java.doc.user.aix64.60%2Fuser%2Fsighand.html

答案 3 :(得分:2)

OS向进程发送信号。默认处理程序将停止进程,但您可以为它定义自己的处理程序。我打赌java VM会这样做。