除算が行われるたびに、除数がゼロと異なるかどうかを単純にチェックしますか(JITによるコードでも)?
つまり、VMは、OSによって以前に強制終了されずに例外をスローすることができますか?
Unix環境では、ゼロ除算がsignal
を介してSIGFPE
ledであるため、JVMはSIGFPE
をトラップし、次にthrow
sおよびArithmeticException
。内部に興味がある場合は、例えばman signal
OPが要求していると思うのは、SIGFPE
ハンドラーが配置されるまでは、ほとんどのプロセスがこのシグナルを受信するとデフォルトのアクションを実行するという事実に基づいています。したがって、例えばCプログラム
int main (int argc, char** argv) { int n = 5 / 0; }
…コンパイルすれば、デフォルトのSIGFPE
→SIG_DFL
アクション。代わりに、JVMのハンドラーは(catch
able)RuntimeException
を発行するため、これらの例外はネイティブに見える方法で処理できます。
いくつかの他の人が指摘したように、そして完全を期すために、実際には、カーネルから生成されたSIGFPE
は、一般にプロセッサ自体からの特別な割り込みからマップされます。したがって、「パイプライン」は次のようなものです
SIGFPE
SIG_DFL
→プロセス死または
SIGFPE
ハンドラー→ユーザーコードのRuntimeException
ArithmeticException
非Unixプラットフォームでは、処理は類似しています。
Javaは他の言語と同様に状況を処理します。ゼロ除算エラーは、割り込みをトリガーするプロセッサ例外を生成します。割り込みは、オペレーティングシステムによって「読み取られ」、ハンドラが登録されている場合はプログラムに転送されます。 Javaはハンドラを登録するので、エラーを受け取り、スタックを上に移動するArithmeticException
に変換します。
JVMは、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;
}
コンパイルして実行すると、次のように出力されます。
el@apollo:~$ gcc -o catch_sigfpe myc.c
el@apollo:~$ ./catch_sigfpe
signal is 8
JVM throws an ArithmeticException here...
el@apollo:~$
オペレーティングシステムは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はそうです。