ART在本机信号处理期间阻止来自JNI的任何Java调用

sdu*_*key 3 java-native-interface android exception-handling native-code

我的项目使用捕获崩溃的模块并在android系统中发送.处理本机崩溃时,本机代码将执行某些操作,然后从JNI执行Java调用.它适用于Dalvik.但它在使用ART的5.0以上的Android版本中失败了.因为ART在本机信号处理期间阻止来自JNI的任何Java调用.它说ART信号处理使用备用信号堆栈,所以在信号处理过程中,不能调用java方法吗?还有其他方法吗?
流:
1.Java调用本机方法,但本机方法崩溃.
2.本机崩溃处理程序捕获信号以处理崩溃.
3.在崩溃处理过程中,调用JNI方法但失败了

12-31 20:36:02.516 7845-7957 A/art: art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: JNI IsSameObject called with pending exception 'java.lang.StackOverflowError' thrown in...
in call to IsSameObject
stack=0x9fff8000-0x9fffa000 stackSize=1036KB
Run Code Online (Sandbox Code Playgroud)

参考:https://code.google.com/p/android/issues/detail?
id = 162663如果有人使用ART和/或Bionic可以调查一下,那就太好了.

And*_*nle 7

您的项目依赖于未定义的行为.

任何信号处理程序都可以安全地调用异步信号安全函数.任何其他函数调用都会调用未定义的行为.在任何情况下依靠Java/Dalvik/ART虚拟机将其自身限制为异步信号安全函数调用是不切实际的,并且很可能只是简单的错误.

您可以随时调用任意信号的处理程序,使VM处于任何可能的状态.没有办法从JNI信号处理程序安全地进行Java调用,并且期望任何人甚至尝试支持这样的调用是不合理的 - synchronized如果允许信号处理程序允许调用synchronized,VM的设计者如何允许信号中断任何方法同一个对象?如果他们这样做,他们就会违背语言的含义而破坏语言synchronized.但如果他们不这样做,他们就会允许死锁,因为这样的调用会试图锁定一个永远无法解锁的对象,因为信号会中断处理.

简而言之,从信号处理程序通过JNI进行的Java调用从根本上说是不可支持的.

他们过去为你工作的事实只能让你期望他们会继续这样做.

你过去很幸运.

它不再有效,你不能指望它将来有用.

即使你以某种方式破解它为你工作,它仍然是根本不健全的.根据POSIX标准,唯一可以在信号处理程序中安全地进行的调用是:

下表定义了一组函数,这些函数应该是信号的可重入或不可中断的,并且应该是异步信号安全的.因此,应用程序可以无限制地调用信号捕获功能:

_Exit()
_exit()
abort()
accept()
access()
aio_error()
aio_return()
aio_suspend()
alarm()
bind()
cfgetispeed()
cfgetospeed()
cfsetispeed()
cfsetospeed()
chdir()
chmod()
chown()
clock_gettime()
close()
connect()
creat()
dup()
dup2()
execle()
execve()
fchmod()
fchown()
fcntl()
fdatasync()
fork()
fpathconf()
fstat()
fsync()
ftruncate()
getegid()
geteuid()
getgid()
getgroups()
getpeername()
getpgrp()
getpid()
getppid()
getsockname()
getsockopt()
getuid()
kill()
link()
listen()
lseek()
lstat()
mkdir()
mkfifo()
open()
pathconf()
pause()
pipe()
poll()
posix_trace_event()
pselect()
raise()
read()
readlink()
recv()
recvfrom()
recvmsg()
rename()
rmdir()
select()
sem_post()
send()
sendmsg()
sendto()
setgid()
setpgid()
setsid()
setsockopt()
setuid()
shutdown()
sigaction()
sigaddset()
sigdelset()
sigemptyset()
sigfillset()
sigismember()
sleep()
signal()
sigpause()
sigpending()
sigprocmask()
sigqueue()
sigset()
sigsuspend()
sockatmark()
socket()
socketpair()
stat()
symlink()
sysconf()
tcdrain()
tcflow()
tcflush()
tcgetattr()
tcgetpgrp()
tcsendbreak()
tcsetattr()
tcsetpgrp()
time()
timer_getoverrun()
timer_gettime()
timer_settime()
times()
umask()
uname()
unlink()
utime()
wait()
waitpid()
write()
Run Code Online (Sandbox Code Playgroud)

上表中未包含的所有功能都被认为对信号不安全.在存在信号的情况下,由IEEE Std 1003.1-2001卷定义的所有功能在信号捕获功能调用或中断时应按照定义运行,但有一个例外:当信号中断不安全功能和信号时 - catch函数调用一个不安全的函数,行为是未定义的.

由于无法保证在信号处理程序中通过JNI进行Java调用只能调用异步信号安全函数,因此除了未定义的行为之外,你无法预料到任何事情.