2014-01-21 72 views
18

每次分割完成時(甚至在JIT編碼中)是否僅檢查除數是否與零不同?Java如何處理除以零?

我的意思是VM如何管理拋出一個異常,而不被操作系統殺死?

+0

「先前遇害」是什麼意思? –

+0

一個字:殭屍! –

+0

它沒有。你必須在某個時候在「catch」塊中自己處理它,否則用戶會在他的臉上看到Excetion,這並不好。 – Renan

回答

31

在Unix環境,在這種劃分被零被signal經由SIGFPE主導,JVM將已安裝的捕集SIGFPE並依次throw S上的一個ArithmeticException信號處理程序。如果您對內部感興趣,請參閱man signal

我相信OP所要求的是基於這樣的事實,除非有一個SIGFPE處理程序到位,否則大多數進程將在接收該信號時採取默認操作,即終止。因此,例如C程序

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

...如果它甚至編譯,將被默認SIGFPESIG_DFL陣亡。 JVM的處理程序會發出(catch able)RuntimeException,以便可以以本機外觀的方式處理這些異常。

正如其他人指出的那樣,並且爲了完整性,事實上從內核生成的SIGFPE通常是從處理器本身的特殊中斷映射而來;因此,「管道」是一樣的東西

  • CPU錯誤陷阱中斷→內核中斷處理程序→SIGFPESIG_DFL→工藝死亡

  • CPU錯誤陷阱中斷→內核中斷處理程序→SIGFPE JVM處理程序→RuntimeExceptionArithmeticException用戶代碼

在非Unix平臺上,處理是類似的。

2

操作系統發送信號給進程。默認的處理程序會停止進程,但是你可以爲它定義自己的處理程序。我敢打賭Java VM確實如此。

6

Java像處理任何其他語言一樣處理這種情況。除以零錯誤會產生處理器異常,從而觸發中斷。如果處理程序已註冊,中斷將被操作系統「讀取」並轉發給程序。由於Java註冊了一個處理程序,它會收到該錯誤,然後將其轉換爲沿着堆棧傳送的ArithmeticException

4

的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; 
} 

編譯並執行它打印這樣的:

[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