zha*_*aen 6 c java linux signals exception-handling
我写了一个非常简单的c程序:
#include<stdio.h>
int main(){
int a=2;
int b=0;
printf("%d\n", a/b);
}
Run Code Online (Sandbox Code Playgroud)
并使用strace运行它:strace ./a.out并获得以下输出(仅粘贴尾部)
... ...
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x7f04c7fb8000, 4096, PROT_READ) = 0
munmap(0x7f04c7f96000, 127640) = 0
--- SIGFPE (Floating point exception) @ 0 (0) ---
+++ killed by SIGFPE +++
Floating point exception
Run Code Online (Sandbox Code Playgroud)
输出符合我的预期,因为它被SIGFPE信号杀死.
但是,用Java编写的相同程序,没有得到SIGFPE信号,有没有人知道java进程如何"除以零"异常?
public class Main {
public static void main(String[] args) {
int a = 2;
int b = 0;
System.out.println(a / b);
}
}
Run Code Online (Sandbox Code Playgroud)
strace java -Xcomp Main
... ...
mprotect(0xf6949000, 8171520, PROT_READ|PROT_WRITE) = 0
mprotect(0xf6949000, 8171520, PROT_READ|PROT_EXEC) = 0
munmap(0xf774f000, 5727) = 0
mmap2(NULL, 331776, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xfffffffff68d0000
mprotect(0xf68d0000, 4096, PROT_NONE) = 0
clone(child_stack=0xf6920494, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xf6920bd8, tls=0xf6920bd8, child_tidptr=0xff9c5520) = 958
futex(0xf6920bd8, FUTEX_WAIT, 958, NULL) = 0
exit_group(0)
Run Code Online (Sandbox Code Playgroud)
在这里,它提出了一个SIGFPE.
你忘了告诉strace
孩子们.添加-f
选项strace
,你应该看到类似的东西:
[pid 2304] read(3, "\312\376\272\276\0\0\0001\0n\n\0\23\0I\t\0\3\0J\7\0K\n\0L\0M\n\0N\0"..., 2369) = 2369
[pid 2304] --- SIGFPE (Floating point exception) @ 0 (0) ---
[pid 2304] rt_sigreturn(0x1c50800) = 5
[pid 2304] write(2, "Exception in thread \"main\" ", 27Exception in thread "main" ) = 27
[pid 2304] write(2, "java.lang.ArithmeticException: /"..., 40java.lang.ArithmeticException: / by zero) = 40
[pid 2304] write(2, "\n", 1
Run Code Online (Sandbox Code Playgroud)
与(普通)C编译程序相比,Java程序在运行时运行,而不是在处理器上运行,并且不依赖于平台.在java中除以零会触发ArithmeticException,如下所示:
Exception in thread "main" java.lang.ArithmeticException: / by zero
Run Code Online (Sandbox Code Playgroud)
来自JLS:
抛出异常有三个原因之一:
Java虚拟机同步检测到异常执行条件.出现这种情况是因为:
表达式的评估违反了语言的正常语义,例如整数除以零,如§15.6中所述.
加载或链接程序的一部分时出错(§12.2,§12.3)
超出了对资源的某些限制,例如使用太多内存
显然这是因为JVM在其代码中有这样的东西:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void fpe_handler(int 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;
}
Run Code Online (Sandbox Code Playgroud)
此外,JVM运行多个线程(参见clone()
上面的日志或ps -eLf
在运行java时执行),因此strace输出只是不完整.
如果更多细节,未处理的SIGFPE表示程序中出现错误.如果java将被SIGFPE杀死,那么它表明JVM中存在错误,而不是在JVM中运行的应用程序中.