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?
Dans un environnement Unix, dans lequel la division par zéro est signal
led via SIGFPE
, la JVM aura installé un gestionnaire de signal qui piège le SIGFPE
et à son tour throw
s 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 SIGFPE
→ SIG_DFL
action. Le gestionnaire de la JVM émet à la place le (catch
able) 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
SIGFPE
SIG_DFL
→ traiter la mortou
SIGFPE
gestionnaire dans JVM → RuntimeException
ArithmeticException
dans le code utilisateurSur les plates-formes non Unix, la gestion est analogue.
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.
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
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.