Проверяет, не отличается ли дивизор от нуля каждый раз, когда выполняется разделение (даже в 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 делает.