Android NDK抛出信号SIGSEGV:通过JNI获取Activity中的GoogleSignInClient后无效的地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android NDK抛出信号SIGSEGV:通过JNI获取Activity中的GoogleSignInClient后无效的地址相关的知识,希望对你有一定的参考价值。

我正在开发LÖVE2D游戏框架的android端口的附加组件,以通过游戏代码提供与Google Play游戏服务的连接。框架的大部分内容都是用C ++编写的。它具有LuaVM,简化了与SDL2的桥接,可以访问所需的任何内容。

要从LuaVM中运行的Lua代码访问Google Play游戏服务,我必须添加包含入口点和包装类的本机C ++模块。从那里我将调用重定向到android.cpp,我必须使用JNI来访问我的主Activity中的函数,因为我必须使用Java包com.google.android.gms.auth.api.signin登录播放器。

这座桥按预期工作。当应用程序加载时,我将其初始化为:

love2d丰富功能的Android /爱情/ src目录/ JNI /爱情/ src目录/模块/ mobsvc / config_MobSvc.h:

static const bool MOBSVC_REQUIRED = false; // Force login into Google Play Games Services

love2d丰富功能的Android /爱情/ src目录/ JNI /爱情/ src目录/模块/ mobsvc / MobSvc.cpp:

MobSvc::MobSvc()
{
    love::android::mobSvcInit(MOBSVC_REQUIRED);
}

^ - 该模块将在应用程序启动时构建。

love2d丰富功能的Android /爱情/ src目录/ JNI /爱情/ src目录/普通/ android.h:

void mobSvcInit(bool required);

love2d丰富功能的Android /爱情/ src目录/ JNI /爱情/ src目录/普通/ android.cpp:

void mobSvcInit(bool required)
{
    bool inp1 = required;

    JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
    jobject activity = (jobject) SDL_AndroidGetActivity();
    jclass clazz (env->GetObjectClass(activity));

    jmethodID methodID = env->GetMethodID(clazz, "mobSvcInit", "(Z)V");
    jboolean jinp1 = (jboolean) inp1;
    env->CallVoidMethod(activity, methodID, jinp1);

    env->DeleteLocalRef(activity);
    env->DeleteLocalRef(clazz);
}

love2d丰富功能的Android /爱情/ src目录/主/ JAVA /组织/ love2d /安卓/ RichGameActivity.java:

public void mobSvcInit(boolean required) {
    // Specify if skipping of the login should be impossible.
    mobSvcRequired = required;

    // Determine if Google Play Games Services is installed on the device.
    PackageManager pm = context.getPackageManager();
    boolean isKindle = (Build.MANUFACTURER.equals("Amazon") && Build.MODEL.equals("Kindle Fire")) || Build.MODEL.startsWith("KF");
    try
    {
        PackageInfo info = pm.getPackageInfo(!isKindle ? "com.android.vending" : "com.amazon.venezia", PackageManager.GET_ACTIVITIES);
        String label = (String) info.applicationInfo.loadLabel(pm);
        mobSvcAvailable = (label != null && !label.equals("Market"));
    }
    catch (PackageManager.NameNotFoundException e)
    {
        mobSvcAvailable = false;
    }

    // Configure sign-in to request the user's ID, email address, and basic
    // profile. ID and basic profile are included in DEFAULT_SIGN_IN.
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
            .requestEmail()
            .build();

    // Build a GoogleSignInClient with the options specified by gso.
    mobSvcSignInClient = GoogleSignIn.getClient(this, gso);

    Log.d("RichGameActivity","Play Games Services initialised.");
}

代码将通过,它将被执行。然而,行mobSvcSignInClient = GoogleSignIn.getClient(this, gso);导致它在文件ANativeWindow_fromSurface(env, s);中的函数Android_JNI_GetNativeWindow中的love2d-rich-android/love/src/jni/SDL2-2.0.5/src/core/android/SDL_android.c上崩溃,之后,这是由SDL2框架完成的JNI操作:

Illustrating signal SIGSEGV: invalid address

如果删除该行,一切都会继续运行而不会出现问题。如需进一步检查,可在此处获取存储库:https://bitbucket.org/MartyMaro/love2d-rich-android/src/c5ad59b16a8b7f9fcc267a9f56e03de959c30b05/?at=MobSvc

我认为这个问题与SDL2不相关,因为在后面的步骤中我继续尝试确保在UI线程上调用代码。在不深入了解LuaVM和LÖVE框架如何工作的情况下,我已经为模块实现了桥接,因此我可以从Lua本身触发上面的代码。因此,调用事物的方式是相同的,但是当VM已经运行并且所有LÖVE模块都已初始化并且代码在UI线程中执行时,代码的执行会更晚。

现在异常在NDK包的jni.h(~/Library/Android/sdk/ndk-bundle/sysroot/usr/include/jni.h)中:

Illustrating signal SIGSEGV: invalid address #2

故障地址似乎是相同的,JNI(因此NDK)在两种情况下都起作用,因此我认为获取Google的登录客户端会导致NDK在下一次JNI操作时失败。我需要一种正确的方法来处理这种情况而不会引起任何问题。我很高兴有任何想法如何解决这个问题。

答案

所以我将我的代码移动到我的Activity的onStart,以摆脱整个NDK依赖,只是为了发现我在运行时得到了NoClassDefFoundError异常。在玩完之后,我看到我在gradle文件中实现了旧版本的auth。

将其更改为我的gradle文件中的最近一个:

api 'com.google.android.gms:play-services-auth:16.0.0'

而且没有抛出异常。之后,我的JNI呼叫确实有效。事实证明,我的堆栈中的异常更高,并且NDK无法正确处理此异常,因此我只得到一个常见的无效地址异常。

如果您遇到类似问题,请在尝试其他方法之前尝试获取最新的库。

以上是关于Android NDK抛出信号SIGSEGV:通过JNI获取Activity中的GoogleSignInClient后无效的地址的主要内容,如果未能解决你的问题,请参考以下文章

Android - JNI / NDK - 与SIGSEV崩溃 - 未触发信号处理

Android NDK GLThread

QNetworkReply 在发出完成信号时抛出 SIGSEGV

Android、CMDTool、stdout 重定向、“致命信号 11 (SIGSEGV)”

如何使用 SIGSEGV 的信号处理程序调试程序

为啥启用 NEON SIMDization 时 Android 会崩溃?信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR)