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

出门莫恨无人随,书中车马多如簇。这篇文章主要讲述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操作:
Android NDK抛出信号SIGSEGV(通过JNI获取Activity中的GoogleSignInClient后无效的地址)

文章图片

【Android NDK抛出信号SIGSEGV(通过JNI获取Activity中的GoogleSignInClient后无效的地址)】如果删除该行,一切都会继续运行而不会出现问题。如需进一步检查,可在此处获取存储库: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)中:
Android NDK抛出信号SIGSEGV(通过JNI获取Activity中的GoogleSignInClient后无效的地址)

文章图片

故障地址似乎是相同的,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无法正确处理此异常,因此我只得到一个常见的无效地址异常。
如果您遇到类似问题,请在尝试其他方法之前尝试获取最新的库。

    推荐阅读