Android Studio调试接收jstring的NDK原生方法时触发art_sigsegv_fault
Android Studio调试NDK接收jstring参数函数触发art_sigsegv_fault问题
问题描述
在Android Studio中调试NDK代码时,若在接收jstring参数的原生函数内设置断点,会立刻触发art_sigsegv_fault错误,应用直接运行完全正常,仅调试时复现。
复现用最简代码
Java层代码(MainActivity.java)
package com.example.ndktestapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); testFoo(5); testBar("/tmp/"); } static native void testFoo(int x); static native void testBar(String path); static { System.loadLibrary("TestLib"); } }
NDK层代码(NDKTestApp.cpp)
#include <jni.h> #include <android/log.h> extern "C" JNIEXPORT void JNICALL Java_com_example_ndktestapp_MainActivity_testFoo(JNIEnv *env, jclass cls, jint x) { __android_log_print(ANDROID_LOG_INFO, "NDKTest", "This is foo"); __android_log_print(ANDROID_LOG_INFO, "NDKTest", "foo x = %d", x); __android_log_print(ANDROID_LOG_INFO, "NDKTest", "foo EXIT"); } extern "C" JNIEXPORT void JNICALL Java_com_example_ndktestapp_MainActivity_testBar(JNIEnv *env, jclass cls, jstring tmpPath) { __android_log_print(ANDROID_LOG_INFO, "NDKTest", "This is Bar"); auto nativeChars = env->GetStringUTFChars(tmpPath, 0); __android_log_print(ANDROID_LOG_INFO, "NDKTest", "Bar path = %s", nativeChars); env->ReleaseStringUTFChars(tmpPath, nativeChars); __android_log_print(ANDROID_LOG_INFO, "NDKTest", "Bar EXIT"); }
问题细节
- 接收
jint类型参数的testFoo(int)函数可正常设置断点、单步调试,无任何异常 - 接收
jstring类型参数的testBar(String)函数断点命中时会立刻崩溃,崩溃栈如下:
art_sigsegv_fault 0x00000000e3785bf0 art::FaultManager::HandleFault(int, siginfo*, void*) 0x00000000e37861a4 art::art_fault_handler(int, siginfo*, void*) (.llvm.6299116872343706859) 0x00000000e3785ebb art::SignalChain::Handler(int, siginfo*, void*) 0x000000005cef31ae __restore_rt 0x00000000e5560bc0 art::Thread::DecodeJObject(_jobject*) const 0x00000000e3bb121a <unknown> 0x00000000e595e06d <unknown> 0x000000005cef1170 art_quick_generic_jni_trampoline 0x00000000e364b133 art_quick_invoke_static_stub 0x00000000e3644af3 art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x00000000e36d9393 art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*) 0x00000000e388f702 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000e3883a3f void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000e3656201 ExecuteSwitchImplAsm 0x00000000e364bde3 art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16375758241455872412) 0x00000000e3878c82 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000e3882c20 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000e3883a21 void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000e3657e4f ExecuteSwitchImplAsm 0x00000000e364bde3 ...
临时规避方案
可以在testBar()内部调用不涉及JNI参数的自定义函数,单步调试该自定义函数时无异常,仅返回testBar()时会触发错误,可基于该特性实现临时调试:
static void notNdk(const char *str) { __android_log_print(ANDROID_LOG_INFO, "NDKTest", "notNdk received %s", str); }
内容的提问来源于stack exchange,提问作者Edward Falk
相关产品推荐
相关产品推荐

