我最近实现了android NDK来隐藏我的应用密钥和秘密。因为每当我在android studio中以调试模式运行我的应用程序时,我都会这样做,我的断点会被sigsegv中断(信号sigsegv:无效地址(错误地址:0x8))。当我的任何进程完全访问NDK时会发生这种情况。我对NDK的新手感到困惑,我感到很困惑。我的C代码非常简单,看起来像:
#include <jni.h>
JNIEXPORT jstring JNICALL
Java_com_my_company_co_utilities_UtilFuncs_getSecretOne(JNIEnv *env, jobject instance) {
return (*env)-> NewStringUTF(env, "my_secret_1");
}
JNIEXPORT jstring JNICALL
Java_com_my_company_co_utilities_UtilFuncs_getSecretTwo(JNIEnv *env, jobject instance) {
return (*env)-> NewStringUTF(env, "my_secret_2");
}
JNIEXPORT jstring JNICALL
JJava_com_my_company_co_utilities_UtilFuncs_getKeyOne(JNIEnv *env, jobject instance) {
return (*env)-> NewStringUTF(env, "my_key_1");
}
JNIEXPORT jstring JNICALL
Java_com_my_company_co_utilities_UtilFuncs_getKeyTwo(JNIEnv *env, jobject instance) {
return (*env)->NewStringUTF(env, "my_key_2");
}
我在我的静态UtilFuncs类中访问它,如:
static {
System.loadLibrary("keys");
}
public static native String getSecretOne();
public static String getSecret() {
return getSecretOne();
}
当我正常运行应用程序时,它运行得很好,但由于这些sigsegv,它使调试无法使用:当我试图读取监视变量时,无效地址错误即将出现。任何人以前遇到过这个或者知道我做错了什么?
更新:更新到Android 9的手机上没有抛出错误,所以我的问题已经解决,但我仍然不知道是什么原因导致了它。对原始原因的任何理论仍然感兴趣。
答案 0 :(得分:1)
这是我要通过过去的JNI崩溃创建的一小部分要检查的内容。
NewStringUTF
的方式,使用字符串作为参数?请查看相同Android NDK documentation。myNativeLib.cpp
extern "C"
JNIEXPORT jstring
JNICALL Java_com_my_company_co_utilities_UtilFuncs_getSecretOne(
JNIEnv *env
,jobject /* this */
)
{
unsigned char my_secret_1[] = {0x1a, 0xb2, 0xb7, 0x39, 0x00, 0x20, 0xb1, 0x0a, 0x33};
return env->NewStringUTF(my_secret_1);
}
答案 1 :(得分:1)
当我遇到相同的线程时,我发现了该线程:添加NDK代码后,在Android Studio(v3.2.1)调试器中运行我的应用程序时出现SIGSEGV错误。在没有调试器的情况下运行它可以正常执行。
我没有找到解决方案,但是我找到了进一步的线索。
这在'libart.so:art_sigsegv_fault'中显示了一个活动断点:
libart中似乎有一些sigsegv故障的历史。我没有找到任何解决方案。但是,禁用此断点确实允许我继续调试应用程序(一种变通方法)。
答案 2 :(得分:0)
这不是解决方案!
我认为您应该坚持使用@NoonanRosenblum解决方案,并尝试在NDK中找到其真正原因并加以解决。
但是如果您没有时间,可以在模块gradle构建文件中注释掉对CMake的调用:
buildTypes {
...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
buildTypes {
...
// externalNativeBuild {
// cmake {
// path "src/main/cpp/CMakeLists.txt"
// }
}
}
不要忘记,如果您调用本机方法,它将崩溃,因此,仅当您要逐步调试并且不想跳过烦人的本机崩溃断点时,才使用它。
答案 3 :(得分:0)
如果您确定C代码始终可以正常工作,也许您想忽略这样的错误并在Java中进行调试。 将“调试配置”-“调试类型”从任何更改为“仅Java”
答案 4 :(得分:0)
万一其他人最近遇到这种情况(2020年10月Android Studio 4.0.1 NDK 19.2.5345600):
在相似的情况下,只有在将参数传递给本机方法(例如jstring)且仅在x86仿真器上时,我才会遇到相同的崩溃。
例如,x86 API 30仿真器上的以下代码一旦遇到断点,便会崩溃,但可以正常运行:
extern "C" JNIEXPORT jstring JNICALL
Java_some_package_SomeClass_someMethod(
JNIEnv* env,
jobject /* this */,
jstring foo) {
// anything ...
}
但是,我可以在x86_64仿真器或物理设备上使用断点调试此代码,而不会出现问题。因此,解决方案是使用x86_64 AVD或始终在设备上调试。