How does Java handle division by zero? [duplicate]

2020-02-10 12:08发布

Does it simply check if divisor is different from zero every time there is division done (even in JIT-ed code)?

I mean how VM manages to throw an exception without being previously killed by the OS?

4条回答
▲ chillily
2楼-- · 2020-02-10 12:47

OS sends signal to the process. Default handler would stop the process, but you can define own handler for it. I bet java VM does.

查看更多
成全新的幸福
3楼-- · 2020-02-10 12:50

The JVM catches the Division by Zero like this with 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;
}

Compile and run it prints this:

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

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

el@apollo:~$

The operating system synchronously raises a SIGFPE exception, the C program catches it, and then the java constructs and feeds you the ArithmeticException and cleans up after itself to stop the Java program.

See more about the signal returned here: http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/index.jsp?topic=%2Fcom.ibm.java.doc.user.aix64.60%2Fuser%2Fsighand.html

查看更多
Deceive 欺骗
4楼-- · 2020-02-10 13:01

In an Unix environment, in which division-by-zero is signalled via SIGFPE, the JVM will have installed a signal handler which traps the SIGFPE and in turn throws an ArithmeticException. If you're interested in the internals, see e.g. man signal

What I believe the OP is asking is based on the fact that, until/unless a SIGFPE handler is in place, most processes will take the default action on receiving this signal, which is to terminate. Thus, e.g. a C program

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

… if it even compiles, will be killed by the default SIGFPESIG_DFL action. The JVM's handler instead issues the (catchable) RuntimeException so that these exceptions can be handled in a native-seeming way.

As several others pointed out, and just for completeness, in point of fact the SIGFPE generated from the kernel is generally mapped from a special interrupt from the processor itself; thus, the “pipeline” is something like

  • CPU error trap interrupt → kernel interrupt handler → SIGFPE SIG_DFL → process death

or

  • CPU error trap interrupt → kernel interrupt handler → SIGFPE handler in JVM → RuntimeException ArithmeticException in user code

On non-Unix platforms the handling is analogous.

查看更多
虎瘦雄心在
5楼-- · 2020-02-10 13:05

Java handles the situation like any other language. A divide by zero error generates a processor exception which triggers an interrupt. The interrupt is "read" by the operating system and forwarded to the program if a handler is registered. Since Java registers a handler, it receives the error and then translates it into an ArithmeticException that travels up the stack.

查看更多
登录 后发表回答