Проверяет, не отличается ли дивизор от нуля каждый раз, когда выполняется разделение (даже в JIT-ed-коде)?
Я имею в виду, как VM удается выбросить исключение, не будучи ранее убитым ОС?
Проверяет, не отличается ли дивизор от нуля каждый раз, когда выполняется разделение (даже в JIT-ed-коде)?
Я имею в виду, как VM удается выбросить исключение, не будучи ранее убитым ОС?
В среде Unix, в которой деление на ноль signal ведется через SIGFPE, JVM установит обработчик сигнала, который перехватит SIGFPE и, в свою очередь, throw a ArithmeticException. Если вы заинтересованы в внутренних компонентах, см., Например, man signal
Я полагаю, что запрос OP основан на том факте, что до тех пор, пока не будет обработчик SIGFPE, большинство процессов примет действие по умолчанию при получении этого сигнала, который должен завершиться. Таким образом, например, программа C
int main (int argc, char** argv) { int n = 5 / 0; }
... если он даже компилируется, будет убит действием по умолчанию SIGFPE → SIG_DFL. Обработчик JVM вместо этого выделяет (catch способный) RuntimeException, поэтому эти исключения могут обрабатываться с помощью наглядного представления.
Как указывали некоторые другие, и только для полноты, на самом деле SIGFPE, сгенерированный из ядра, обычно отображается из специального прерывания от самого процессора; таким образом, "конвейер" - это что-то вроде
SIGFPE SIG_DFL → процесс смертиили
SIGFPE в JVM → RuntimeException ArithmeticException в коде пользователяНа платформах, отличных от Unix, обработка аналогична.
Java обрабатывает ситуацию как любой другой язык. Ошибка деления на нуль генерирует исключение процессора, которое вызывает прерывание. Прерывание "считывается" операционной системой и отправляется в программу, если обработчик зарегистрирован. Поскольку Java регистрирует обработчик, он получает ошибку и затем переводит ее в ArithmeticException, который перемещается вверх по стеку.
JVM ловит раздел с помощью Zero, как это, на 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;
}
Скомпилируйте и запустите его:
[email protected]:~$ gcc -o catch_sigfpe myc.c
[email protected]:~$ ./catch_sigfpe
signal is 8
JVM throws an ArithmeticException here...
[email protected]:~$
Операционная система синхронно вызывает исключение 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
OS посылает сигнал процессу. Обработчик по умолчанию остановит процесс, но вы можете определить для него собственный обработчик. Я уверен, что java VM делает.