简体   繁体   English

如何调试:应用程序中的JNI检测到错误:使用无效的jobject

[英]How to debug: JNI DETECTED ERROR IN APPLICATION: use of invalid jobject

I am working on a Xamarin Android project, and I get the following error (full log here ) 我正在处理Xamarin Android项目,但出现以下错误(完整日志在此处

11-07 08:28:09.067: A/art(7164): art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xd4fd90e0
11-07 08:28:09.067: A/art(7164): art/runtime/java_vm_ext.cc:410] "Thread-1973" prio=10 tid=26 Runnable
11-07 08:28:09.067: A/art(7164): art/runtime/java_vm_ext.cc:410]   | group="main" sCount=0 dsCount=0 obj=0x137270a0 self=0xc89d4900
11-07 08:28:09.067: A/art(7164): art/runtime/java_vm_ext.cc:410]   | sysTid=9034 nice=-11 cgrp=default sched=0/0 handle=0xd4b3a930
11-07 08:28:09.067: A/art(7164): art/runtime/java_vm_ext.cc:410]   | state=R schedstat=( 310795035 15833156 94 ) utm=24 stm=7 core=5 HZ=100
11-07 08:28:09.067: A/art(7164): art/runtime/java_vm_ext.cc:410]   | stack=0xd4a3c000-0xd4a3e000 stackSize=1022KB
11-07 08:28:09.067: A/art(7164): art/runtime/java_vm_ext.cc:41n0]   | held mutexes= "mutator lock"(shared held)

when try to play a movie (custom third party ExoPlayer wrapper library) while in airplane mode. 在飞行模式下尝试播放电影(自定义第三方ExoPlayer包装器库)时。 I am not seeking help to find the bug with only this info, but only a way to debug app. 我不是在寻求帮助来仅通过此信息来查找错误,而仅是一种调试应用程序的方式。 When crash appears the debugger is disconnected. 当出现崩溃时,调试器将断开连接。

Also I have seen this thread: https://bugzilla.xamarin.com/show_bug.cgi?id=45281 on Xamarin bugzilla, but when I enable GC logs with the following: 我也看到了这个线程:Xamarin bugzilla上的https://bugzilla.xamarin.com/show_bug.cgi?id=45281 ,但是当我使用以下命令启用GC日志时:

$ adb shell setprop debug.mono.log gref,gc

the app does not crash!!! 该应用程序不会崩溃!!!

I am testing on device Samsung SM-G930F aka Samsung S7 and using API level 23 . 我正在设备Samsung SM-G930F aka Samsung S7上进行测试,并使用API level 23 The error appears also on other devices. 该错误也出现在其他设备上。

My build setup: 我的构建设置:

Xamarin Studio Community
Version 6.1.1 (build 15)
Installation UUID: b3096ed4-0118-4e0d-87f4-a1fe79ffc301
Runtime:
    Mono 4.6.1 (mono-4.6.0-branch-c8sr0/ef43c15) (64-bit)
    GTK+ 2.24.23 (Raleigh theme)

    Package version: 406010005

NuGet
Version: 3.4.3.0

Xamarin.Profiler
Not Installed

Apple Developer Tools
Xcode 8.1 (11544)
Build 8B62

Xamarin.Mac
Version: 2.10.0.105 (Xamarin Studio Community)

Xamarin.iOS
Version: 10.0.1.10 (Xamarin Studio Community)
Hash: ad1cd42
Branch: cycle8-sr0-xi
Build date: 2016-10-03 15:18:44-0400

Xamarin.Android
Version: 7.0.1.3 (Xamarin Studio Community)
Android SDK: /Users/andi/Library/Android/sdk
    Supported Android versions:
        5.0 (API level 21)
        6.0 (API level 23)
        7.0 (API level 24)

SDK Tools Version: 25.2.2
SDK Platform Tools Version: 24.0.3
SDK Build Tools Version: 23.0.1

Java SDK: /usr
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

Xamarin Android Player
Version: 0.6.5
Location: /Applications/Xamarin Android Player.app

Build Information
Release ID: 601010015
Git revision: fa52f02641726146e2589ed86ec4097fbe101888
Build date: 2016-09-22 08:03:02-04
Xamarin addins: 75d65712af93d54dc39ae4c42b21dfa574859fd6
Build lane: monodevelop-lion-cycle8-sr0

Operating System
Mac OS X 10.12.1
Darwin Pentagon.local 16.1.0 Darwin Kernel Version 16.1.0
    Thu Oct 13 21:26:57 PDT 2016
    root:xnu-3789.21.3~60/RELEASE_X86_64 x86_64

EDIT: 编辑:

With gref enabled log (no crash): https://gist.github.com/sanandrea/b9a837b8c885ac037c4f4bc6e8030d10 启用gref的日志(无崩溃): https ://gist.github.com/sanandrea/b9a837b8c885ac037c4f4bc6e8030d10

Without gref enabled (crash): https://gist.github.com/sanandrea/d2c5c895b4bc15f45381421c9c21b859 没有启用gref(崩溃): https ://gist.github.com/sanandrea/d2c5c895b4bc15f45381421c9c21b859

EDIT 2 This can be tagged as #HeisenBug 编辑2可以将其标记为#HeisenBug

Ideally how you would debug this type of situation is very close to the path you are following. 理想情况下,如何调试这种情况非常接近要遵循的路径。

The first thing that you'd want to do is enable gref logs via adb or an environment.txt file with a Build Action of AndroidEnvironment ( Note: There are limitations using the latter option - https://developer.xamarin.com/guides/android/advanced_topics/environment/#Overview ): 您要做的第一件事是通过adb或具有AndroidEnvironmentBuild Actionenvironment.txt文件启用gref日志( 注意:使用后一种选项存在一些局限性AndroidEnvironment : //developer.xamarin.com/guides / android / advanced_topics / environment /#Overview ):

adb shell setprop debug.mono.log gref

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

Great! 大! Now we can see the lifetime of respective global references(gref for short). 现在我们可以看到各个全局引用的生命周期(简称gref)。 This is a starting point. 这是一个起点。 For future reference in this post, let's define a few items: 为了将来在本文中参考,让我们定义一些项目:

  • gref - Global Reference gref-全球参考
  • wref - Weak Global Reference wref-弱全局参考

Ideally we want to test this on a physical device as it will have a limit of ~52000 grefs. 理想情况下,我们希望在物理设备上对此进行测试,因为它的限制为〜52000 gref。 Whereas an emulator has a limit of 2000 grefs. 而仿真器的上限为2000 gref。 As you imagine this can be quite troublesome if you cross this line quite quickly(Which you just might). 正如您所想象的那样,如果您很快越过这条线可能会很麻烦(您可能会这样做)。

Next we can follow the convention of four main messages we want to know about: 接下来,我们可以遵循我们要了解的四个主要消息的约定:

  • Start with +g+ - gref creation +g+开始-创建gref
  • Start with -g- - gref destruction -g-开始-gref破坏
  • Start with +w+ - wref creation +w+开始-创建wref
  • Start with -w- - wref destruction -w-开始-wref破坏

You might also notice that on these lines there is a grefc value. 您可能还会注意到,在这些行上有一个grefc值。 This refers to the gref count which is the total amount that Xamarin.Android has made. 这是指gref count ,它是Xamarin.Android已完成的总量。 You can then assume the same for the grefwc value being the wref count . 然后,可以对grefwc值(即wref count假定相同的值。 Let's define this in a small table: 让我们在一个小表中定义它:

  • grefc - gref count grefc -gref计数
  • grefwc - wref count grefwc -wref计数

Let' take a look at an example of this syntax: 让我们看一下这种语法的示例:

I/monodroid-gref(12405): +g+ grefc 108 gwrefc 0 obj-handle 0x40517468/L -> new-handle 0x40517468/L from    at Java.Lang.Object.RegisterInstance(IJavaObject instance, IntPtr value, JniHandleOwnership transfer)
I/monodroid-gref(12405):    at Java.Lang.Object.SetHandle(IntPtr value, JniHandleOwnership transfer)
I/monodroid-gref(12405):    at Java.Lang.Object..ctor(IntPtr handle, JniHandleOwnership transfer)
I/monodroid-gref(12405):    at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler, Boolean removable)
I/monodroid-gref(12405):    at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler)
I/monodroid-gref(12405):    at Android.App.Activity.RunOnUiThread(System.Action action)
I/monodroid-gref(12405):    at Mono.Samples.Hello.HelloActivity.UseLotsOfMemory(Android.Widget.TextView textview)
I/monodroid-gref(12405):    at Mono.Samples.Hello.HelloActivity.<OnCreate>m__3(System.Object o)
I/monodroid-gref(12405): handle 0x40517468; key_handle 0x40517468: Java Type: `mono/java/lang/RunnableImplementor`; MCW type: `Java.Lang.Thread+RunnableImplementor`
I/monodroid-gref(12405): Disposing handle 0x40517468
I/monodroid-gref(12405): -g- grefc 107 gwrefc 0 handle 0x40517468/L from    at Java.Lang.Object.Dispose(System.Object instance, IntPtr handle, IntPtr key_handle, JObjectRefType handle_type)
I/monodroid-gref(12405):    at Java.Lang.Object.Dispose()
I/monodroid-gref(12405):    at Java.Lang.Thread+RunnableImplementor.Run()
I/monodroid-gref(12405):    at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
I/monodroid-gref(12405):    at System.Object.c200fe6f-ac33-441b-a3a0-47659e3f6750(IntPtr , IntPtr )
I/monodroid-gref(27679): +w+ grefc 1916 gwrefc 296 obj-handle 0x406b2b98/G -> new-handle 0xde68f4bf/W from take_weak_global_ref_jni
I/monodroid-gref(27679): -w- grefc 1915 gwrefc 294 handle 0xde691aaf/W from take_global_ref_jni

The handle or obj-handle value is the JNI handle value, and the character after the ' /' is the type of handle value: /L for local reference, /G for global references, and /W for weak global references. handle或obj-handle值是JNI句柄值,'/'之后的字符是句柄值的类型:/ L表示本地引用,/ G表示全局引用,/ W表示弱全局引用。

Now let's take a look into various scenarios with this note in mind: 现在,请记住以下注意事项,以了解各种情况:

# Java instance is created and wrapped by a MCW
I/monodroid-gref(27679): +g+ grefc 2211 gwrefc 0 obj-handle 0x4066df10/L -> new-handle 0x4066df10/L from ...
I/monodroid-gref(27679): handle 0x4066df10; key_handle 0x4066df10: Java Type: `android/graphics/drawable/TransitionDrawable`; MCW type: `Android.Graphics.Drawables.TransitionDrawable`

# A GC is being performed...
I/monodroid-gref(27679): +w+ grefc 1953 gwrefc 259 obj-handle 0x4066df10/G -> new-handle 0xde68f95f/W from take_weak_global_ref_jni
I/monodroid-gref(27679): -g- grefc 1952 gwrefc 259 handle 0x4066df10/G from take_weak_global_ref_jni

# Object is still alive, as handle != null
# wref turned back into a gref
I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x4066df10
I/monodroid-gref(27679): +g+ grefc 1930 gwrefc 39 obj-handle 0xde68f95f/W -> new-handle 0x4066df10/G from take_global_ref_jni
I/monodroid-gref(27679): -w- grefc 1930 gwrefc 38 handle 0xde68f95f/W from take_global_ref_jni

# Object is dead, as handle == null
# wref is freed, no new gref created
I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x0
I/monodroid-gref(27679): -w- grefc 1914 gwrefc 296 handle 0xde68f95f/W from take_global_ref_jni

You can see my other answer on the Xamarin.Android Garbage Collection Algorithm to see exactly when these handles get changed. 您可以在Xamarin.Android垃圾回收算法上看到我的其他答案,以确切了解何时更改了这些句柄。

So now that you have an idea of what patterns you can see during various scenarios, it will help you figure out what is going on at the time of your invalid jobject . 因此,既然您已经了解了在各种情况下可以看到的模式,那么它将帮助您弄清楚invalid jobject发生了什么。

Now is the fun part, but also can be the hardest part: 现在是有趣的部分,但也可能是最困难的部分:

You need to now replicate the crash while this logging is enabled. 启用此日志记录后,您现在需要复制崩溃。

Once you have done that, you need to take the new error message you received and the handle given to you. 完成此操作后,您需要处理收到的新错误消息以及赋予您的句柄。 In your original post it refers to: 在您的原始帖子中,它指的是:

JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xd4fd90e0

However it's possible that this handle will change throughout different replications of the issue. 但是,此问题的handle可能会在问题的不同复制过程中发生变化。 However once you have that handle , you can use a tool like grep to search for the handle string: 但是,一旦有了该handle ,就可以使用grep类的工具来搜索handle字符串:

0xd4fd90e0

Once you've done this, you can take a look at what state this handle is in via the sample snippet above and make a fix in the respective area. 完成此操作后,您可以通过上方的示例代码查看此handle状态,并在相应区域进行修复。 (Premature GC, Object manually being disposed, etc) (过早的GC,手动处置对象等)

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

$ adb shell setprop debug.mono.log gref,gc

the app does not crash!!! 该应用程序不会崩溃!!!

I am testing on device Samsung SM-G930F aka Samsung S7 and using API level 23. 我正在设备Samsung SM-G930F aka Samsung S7上进行测试,并使用API​​级别23。

I had Exactly the same!!! 我完全一样!!!

In Android properties, 在Android属性中,

Turning off Shared Runtime helped me. 关闭共享运行时对我有帮助。

在此处输入图片说明

I just got this issue and the problem was not an object management issue. 我只是遇到了这个问题,而这个问题不是对象管理问题。

The issue was a C calling back into a java method with the wrong number of arguments. 问题是C用错误的参数数调用java方法。

If the C code doesn't provide enough arguments the java code will have garbage in the objects passed in and using them will create the "JNI DETECTED ERROR IN APPLICATION: use of invalid jobject" error, but the value shown is not related to any object that has been created before. 如果C代码没有提供足够的参数,则Java代码将在传入的对象中包含垃圾,使用它们将创建“ JNI DETECTED ERROR IN APPLICATION:use invalid jobject”错误,但显示的值与任何之前创建的对象。

If this error arise from a C/C++ call into java, make sure all the arguments are provided as the compilers will not check the type or number of arguments. 如果此错误是由于对Java的C / C ++调用引起的,请确保提供了所有参数,因为编译器将不会检查参数的类型或数量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JNI 在应用程序中检测到错误:为内部类调用 NewObject 时使用无效的作业 - JNI DETECTED ERROR IN APPLICATION: use of invalid jobject when calling NewObject for innerclass 如何使用Jobject数组? (Jni) - How to use a jobject array ? (Jni) JNI在应用程序中检测到错误:使用已删除的本地引用0x1 - JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x1 JNI检测到应用程序错误:使用已删除的弱全局引用 - JNI DETECTED ERROR IN APPLICATION: use of deleted weak global reference Android(ART)崩溃,错误JNI DETECTED ERROR IN APPLICATION:jarray是无效的堆栈间接引用表或无效的引用 - Android (ART) crash with error JNI DETECTED ERROR IN APPLICATION: jarray is an invalid stack indirect reference table or invalid reference 为什么调用CallStaticVoidMethod会将无效的jobject与JNI一起使用 - Why called CallStaticVoidMethod throwed use of invalid jobject with JNI Android(ART)崩溃,错误JNI DETECTED ERROR IN APPLICATION:jstring是无效的本地引用 - Android (ART) crash with error JNI DETECTED ERROR IN APPLICATION: jstring is an invalid local reference JNI在Brother SDK上的应用程序中检测到错误 - JNI DETECTED ERROR IN APPLICATION on Brother SDK Android JNI 在应用程序中检测到错误:调用 JNI GetMethodID 时出现未决异常 - Android JNI DETECTED ERROR IN APPLICATION: JNI GetMethodID called with pending exception 如何在JNI中访问Jobject的值 - How to access values of a jobject in JNI
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM