如何诊断Xamarin Android弱参考表溢出的原因?

问题描述:

我有几个用户的报告,说我的应用在大约5分钟的密集使用后崩溃了。我收到了Google Play上的崩溃日志,并在下面附上了一个示例。该消息似乎是:如何诊断Xamarin Android弱参考表溢出的原因?

JNI ERROR(APP错误):弱全局引用表溢出(最大值= 51200)”

我不熟悉JNI,并希望使任何意见/解释/关于如何解决这个问题的建议。可能的原因是我的代码中的东西没有被清理干净,但是什么?

,这个问题已经被报告上的设备的Nexus 5.x的银河S7的Nexus 6

相关代码可以在我的开源项目中找到:https://gitlab.com/hodgskin-callan/Invention。但是,我没有最低限度的代码来重现此问题,并且它不会在我的Nexus 9上重现。我怀疑此问题不会影响大多数Android用户。

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 
Build fingerprint: 'google/bullhead/bullhead:7.1.1/N4F26T/3687331:user/release-keys' 
Revision: 'rev_1.0' 
ABI: 'arm' 
pid: 10404, tid: 10404, name: .x10host.pathos >>> com.x10host.pathos <<< 
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- 
Abort message: 'art/runtime/indirect_reference_table.cc:132] JNI ERROR (app bug): weak global reference table overflow (max=51200)' 
    r0 00000000 r1 000028a4 r2 00000006 r3 00000008 
    r4 f300558c r5 00000006 r6 f3005534 r7 0000010c 
    r8 00000000 r9 0000000a sl 00001785 fp f0385400 
    ip 0000000b sp ffde7b50 lr f1a065e7 pc f1a08e44 cpsr 200f0010 

backtrace: 
    #00 pc 00049e44 /system/lib/libc.so (tgkill+12) 
    #01 pc 000475e3 /system/lib/libc.so (pthread_kill+34) 
    #02 pc 0001d8a5 /system/lib/libc.so (raise+10) 
    #03 pc 000193f1 /system/lib/libc.so (__libc_android_abort+34) 
    #04 pc 00017034 /system/lib/libc.so (abort+4) 
    #05 pc 0031a5f1 /system/lib/libart.so (_ZN3art7Runtime5AbortEPKc+328) 
    #06 pc 000b5205 /system/lib/libart.so (_ZN3art10LogMessageD2Ev+1132) 
    #07 pc 001bc42b /system/lib/libart.so (_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE+194) 
    #08 pc 0023a097 /system/lib/libart.so (_ZN3art9JavaVMExt16AddWeakGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE+46) 
    #09 pc 0027f483 /system/lib/libart.so (_ZN3art3JNI16NewWeakGlobalRefEP7_JNIEnvP8_jobject+418) 
    #10 pc 0000de14 /data/app/com.x10host.pathos-2/lib/arm/libmonodroid.soapp/com.x10host.pathos-2/lib/arm/libmonodroid.so 
+0

有一整段关于gref日志记录的文档,您可以通过它来跟踪它:https://developer.xamarin.com/guides/android/troubleshooting/troubleshooting/#Global_Reference_Messages –

+0

谢谢,我已阅读本文并启用日志记录。它几乎整个时间都表示gwrefc 0。我希望看到它随着时间的推移而增长。你知道是否有办法在运行时查询grefc和gwrefc的当前状态?我可以给我的用户定制一个APK进行测试。 –

+0

你可以设置一个环境属性:https://developer.xamarin.com/guides/android/advanced_topics/environment/#Xamarin.Android_System_Properties然后在应用程序崩溃时向用户请求一个'adb logcat'?如果你无法在本地复制,这会有点困难。 –

有关于这个问题很长,但非常有用的一条文档编制的位置:

https://developer.xamarin.com/guides/android/troubleshooting/troubleshooting/#Global_Reference_Messages

对于第一次通过,你应该尝试通过.txt文件,以使系统属性,有它的Build Action设置为$(AndroidEnvironment)

debug.mono.log gref

https://developer.xamarin.com/guides/android/advanced_topics/environment/#Xamarin.Android_System_Properties

然后,您将从包含此日志记录的设备获取adb logcat

然而,如果不工作,你赞成:

你应该能够直接通过查询:

Java.Interop.JniRuntime.CurrentRuntime.GlobalReferenceCount

Java.Interop.JniRuntime.CurrentRuntime.WeakGlobalReferenceCount

当地的引用也跟踪了Java.Interop.JniEnvironment.LocalReferenceCount这是一个线程本地值。

+0

当我阅读那篇文章时,我没有看到以编程方式查询部分!虽然,我认为WeakGlobalReferenceCount总是在Xamarin Android上返回-1。第81行:https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Android.Runtime/AndroidRuntime.cs。我查了一下,因为我在Nexus 9上得到-1。 –

+0

这是因为我添加了该部分。我确实认为-1可能是一个问题。您应该可以使用'LocalReferenceCount',但是https://github.com/xamarin/java.interop/blob/a1d3ecc8ba6e67b96ae1c633194b0e78c2ac5c23/src/Java.Interop/Java.Interop/JniEnvironment.cs#L35-L37 –

+0

好吧,我没有结论,但我确实收到了一位用户的新反馈。他观察到,当grefc超过46,000时,应用程序崩溃。当我重现Nexus 9上的情况时,该应用不会崩溃,并且grefc重置为约6000。有没有问题的代码与grefc清理有关? –