Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In java, "5/0" statement doesn't fire SIGFPE signal on my Linux machine, why?

I wrote a very simple c program:

#include<stdio.h>

int main(){
    int a=2;
    int b=0;
    printf("%d\n", a/b);
}

and run it with strace: strace ./a.out and get below output (only paste tail part)

... ...
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

The output matches my expectation, as it was killed by SIGFPE signal.

However, the same program written in Java, doesn't get SIGFPE signal, does anybody know how java processes "divide by zero" exception?

public class Main {

  public static void main(String[] args) {
    int a = 2;
    int b = 0;
    System.out.println(a / b);
  }
}

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)  
like image 428
zhangfaen Avatar asked Nov 21 '11 07:11

zhangfaen


2 Answers

Here, it raises a SIGFPE.

You forgot to tell strace to follow children. Add the -f option to strace and you should see something similar to:

[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
like image 196
ninjalj Avatar answered Nov 09 '22 01:11

ninjalj


Obviously this is because JVM has something like this in its code:

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

Also JVM runs multiple threads (see clone() in the log above or do ps -eLf when java is running) so that strace output is just incomplete.

If a little more detail, unhandled SIGFPE indicates an error in the program, in which it occurred. And if java would be killed by SIGFPE, it would indicate than an error is in JVM, but not in your app, running inside JVM.

like image 39
praetorian droid Avatar answered Nov 09 '22 01:11

praetorian droid