web-dev-qa-db-ja.com

Javaはゼロによる除算をどのように処理しますか?

除算が行われるたびに、除数がゼロと異なるかどうかを単純にチェックしますか(JITによるコードでも)?

つまり、VMは、OSによって以前に強制終了されずに例外をスローすることができますか?

18
mrpyo

Unix環境では、ゼロ除算がsignalを介してSIGFPEledであるため、JVMはSIGFPEをトラップし、次にthrowsおよびArithmeticException。内部に興味がある場合は、例えばman signal

OPが要求していると思うのは、SIGFPEハンドラーが配置されるまでは、ほとんどのプロセスがこのシグナルを受信するとデフォルトのアクションを実行するという事実に基づいています。したがって、例えばCプログラム

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

…コンパイルすれば、デフォルトのSIGFPESIG_DFLアクション。代わりに、JVMのハンドラーは(catchable)RuntimeExceptionを発行するため、これらの例外はネイティブに見える方法で処理できます。

いくつかの他の人が指摘したように、そして完全を期すために、実際には、カーネルから生成されたSIGFPEは、一般にプロセッサ自体からの特別な割り込みからマップされます。したがって、「パイプライン」は次のようなものです

  • CPUエラートラップ割り込み→カーネル割り込みハンドラー→SIGFPESIG_DFL→プロセス死

または

  • CPUエラートラップ割り込み→カーネル割り込みハンドラー→JVMのSIGFPEハンドラー→ユーザーコードのRuntimeExceptionArithmeticException

非Unixプラットフォームでは、処理は類似しています。

32
BRPocock

Javaは他の言語と同様に状況を処理します。ゼロ除算エラーは、割り込みをトリガーするプロセッサ例外を生成します。割り込みは、オペレーティングシステムによって「読み取られ」、ハンドラが登録されている場合はプログラムに転送されます。 Javaはハンドラを登録するので、エラーを受け取り、スタックを上に移動するArithmeticExceptionに変換します。

7
64BitBob

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

6
Eric Leschinski

OSはプロセスにシグナルを送信します。デフォルトのハンドラーはプロセスを停止しますが、独自のハンドラーを定義できます。 Java VMはそうです。

2
Michał Šrajer