web-dev-qa-db-fra.com

Comment Java gère-t-il la division par zéro?

Vérifie-t-il simplement si le diviseur est différent de zéro à chaque fois qu'une division est effectuée (même en code JIT)?

Je veux dire comment VM parvient à lever une exception sans être préalablement tué par le système d'exploitation?

18
mrpyo

Dans un environnement Unix, dans lequel la division par zéro est signalled via SIGFPE, la JVM aura installé un gestionnaire de signal qui piège le SIGFPE et à son tour throws un ArithmeticException. Si vous êtes intéressé par les internes, voir par exemple man signal

Ce que je pense que l'OP demande est basé sur le fait que, jusqu'à ce que/à moins qu'un gestionnaire SIGFPE soit en place, la plupart des processus prendront l'action par défaut à la réception de ce signal, qui doit se terminer. Ainsi, par ex. un programme C

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

… S'il compile même, sera tué par la valeur par défaut SIGFPESIG_DFL action. Le gestionnaire de la JVM émet à la place le (catchable) RuntimeException afin que ces exceptions puissent être gérées de manière native.

Comme plusieurs autres l'ont souligné, et par souci d'exhaustivité, en fait, le SIGFPE généré à partir du noyau est généralement mappé à partir d'une interruption spéciale du processeur lui-même; ainsi, le "pipeline" est quelque chose comme

  • Interruption d'interruption d'erreur CPU → gestionnaire d'interruption du noyau → SIGFPESIG_DFL → traiter la mort

ou

  • Interruption d'interruption d'erreur CPU → gestionnaire d'interruption du noyau → SIGFPE gestionnaire dans JVM → RuntimeExceptionArithmeticException dans le code utilisateur

Sur les plates-formes non Unix, la gestion est analogue.

32
BRPocock

Java gère la situation comme n'importe quel autre langage. Une erreur de division par zéro génère une exception de processeur qui déclenche une interruption. L'interruption est "lue" par le système d'exploitation et transmise au programme si un gestionnaire est enregistré. Puisque Java enregistre un gestionnaire, il reçoit l'erreur puis la traduit en ArithmeticException qui remonte la pile.

7
64BitBob

La JVM attrape la Division by Zero comme ceci avec 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;
}

Compilez-le et exécutez-le affiche ceci:

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

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

el@apollo:~$

Le système d'exploitation déclenche de façon synchrone une exception SIGFPE, le programme C la capture, puis le Java vous construit et vous alimente l'Exception Arithmetic et nettoie après lui-même pour arrêter le programme Java.

En savoir plus sur le signal renvoyé ici: http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/index.jsp?topic=%2Fcom.ibm.Java.doc.user.aix64.60 % 2Fuser% 2Fsighand.html

6
Eric Leschinski

Le système d'exploitation envoie un signal au processus. Le gestionnaire par défaut arrêterait le processus, mais vous pouvez définir son propre gestionnaire. Je parie Java VM fait.

2
Michał Šrajer